Patterns

2.6.15

Icons

 Anchor  

Feather Icons

<svg class="icon-ui text-blue">
  <use xlink:href="#feather-feather"></use>
</svg>

NYCO Patterns integrates the Feather open source icon set for use as user interface icons. The classname icon-ui is needed to set the stroke width and default dimensions for UI icons. By default the dimensions for these icons are 24px 24px (width and height).

When integrating UI icons it is recommended to install the Feather Icon Package independently in your project via NPM. It contains a JavaScript API, Node.js API, and SVG sprite. Other front-end framework implementations include:

Each package may have different methods of implementation to take into consideration. For prototyping svg files can be downloaded from feathericons.com individually or from the project Figma file.

You may also use the sprite included with this repository. The <use> tag’s xlink:href attribute corresponds to the Feather icon slug which can be referenced on the feathericons.com site. Every ID is prefixed with #feather-. Be sure to provide the appropriate attribution to the Feather project.

Icon Usage

Inline SVG Sprites

To use SVG icons, you can inline each sprite in your page markup by adding it to a template partial or copy/pasting the SVG sprite file contents into the base template of your application or site.

  • Icon sprite. Includes logos, custom icons, checkbox, radio, and select box graphics. Path /dist/svg/icons.svg
  • Feather icon sprite. Path /dist/svg/feather.svg

However, it is recommended to asynchronously retrieve the file and inline it to reduce the overall page size. NYCO Patterns uses fetch() to retrieve the sprite and add it to the DOM on page load. This will cache the sprite file without including it in the page to decrease the size of each page.

To import the icon through the global NYCO Patterns script use the following code:

var nyco = new NYCO();

nyco.icons();
nyco.icons('svg/feather.svg');

The script expects the default icon sprite path to be located at the path svg/icons.svg (relative to the displayed page). To overwrite this, pass a path string as an argument to the method:

nyco.icons('path/to/icons.svg');

ES Module

This method is a wrapper around the Patterns Scripts icon utility which is included as a dependency of this project. The utility can be imported as an ES module and instantiated separately.

import Icons from '@nycopportunity/pttrn-scripts/src/icons/icons';

new Icons(); // Inline the icon sprite
new Icons('svg/feather.svg'); // Inline the Feather icon sprite

// or specify custom local path

new Icons('path/to/icons.svg');
new Icons('path/to/feather.svg');

// or CDN

new Icons('https://cdn.jsdelivr.net/gh/cityofnewyork/nyco-patterns@v2.6.15/dist/svg/icons.svg');
new Icons('https://cdn.jsdelivr.net/gh/cityofnewyork/nyco-patterns@v2.6.15/dist/svg/feather.svg');

Markup

Once the sprite is inlined on the desired page to display an icon on, individual icons can be referenced with the SVG <use> tag. To change the color of inline SVG icon shapes that have their fill set as currentColor, use Tailwindcss text color utilities.

In this logo example, the role attribute is set to image and the <title> tag is set inside the SVG. This enables compatibility with screen readers to read the title as they would alternative text in images.

The NYC Opportunity Logo
<svg class="icon-logo-nyco icon-large text-navy" role="img">
  <title id="icon-logo-nyco-title">
    The NYC Opportunity Logo
  </title>

  <use xlink:href="#icon-logo-nyco"></use>
</svg>

It may not always be necessary to have screen readers read icons if they are purely decorative or are associated with a text label. They can be hidden with the aria-hidden attribute. In the following example an icon is included in a link that has a text label

<a href="#" class="inline-flex items-center">
  <svg class="icon-ui mie-1" aria-hidden="true">
    <use xlink:href="#feather-feather"></use>
  </svg> Feather Label
</a>

Icon size utilities

To manage the size of the icons, use the icon size utilities. The dimensions are based on the 8px grid and include the following sizes;

Class Dimensions
icon-1 8px 8px
icon-2 16px 16px
icon-3 24px 24px
icon-4 32px 32px
icon-5 40px 40px
icon-6 48px 48px
icon-7 56px 56px
icon-8 64px 64px
icon-9 72px 72px
icon-10 80px 80px
icon-11 88px 88px
icon-12 96px 96px
icon-large 136px 136px
icon-xlarge 256px 256px

Maintaining the size of the icon sprite

Care should be taken to reduce the size of the icon sprite in production builds by only including icons that are used in your project. The Gulp.js script below is a rough example of how to build an icon sprite by examining the static template files in a view directory.

const VIEWS = 'path/to/view/templates';
const PATTERNS = 'path/to/patterns/source';

let list = [];

/**
 * Build the icon list from templates
 */
gulp.task('svgs:list', () => gulp.src([
    `${VIEWS}/**/*.twig`,
    `${VIEWS}/**/*.vue`
  ]).pipe(through.obj((chunk, encoding, callback) => {
    const regex = /xlink:href="([\S]*)#([\S]+)"/g
    let content = chunk.contents.toString('utf8');
    let m;

    while ((m = regex.exec(content)) !== null) {
      list.push(m[2]);
    }

    callback(null, chunk);
  }))
);

/**
 * Add full path name to the sprite source
 */
gulp.task('svgs:add', () => gulp.src('assets/svg/icons.svg')
  .pipe(through.obj((chunk, encoding, callback) => {
    list = list.filter((item, index) => list.indexOf(item) === index)
      .map(item => `${PATTERNS}/src/svg/${item}.svg`);

    callback(null, chunk);
  }))
);

/**
 * Add optimize and store icons in a new sprite
 */
gulp.task('svgs:compile', () =>
  gulp.src(list)
    .pipe(svgmin())
    .pipe(svgstore({
      inlineSvg: true
    }))
    .pipe(rename('icons.svg'))
    .pipe(gulp.dest('assets/svg/'))
    .pipe(hashFilename({format: HASH_FORMAT}))
    .pipe(gulp.dest('assets/svg/'))
);