svg icon

👻 A lightweight library that makes it easier to use SVG icons in your Angular Application

260
35
TypeScript


A lightweight library that makes it easier to use SVG icons in your Angular Application

MIT
commitizen
PRs
styled with prettier
All Contributors
ngneat
spectator

The svg-icon library enables using the <svg-icon> tag to directly display SVG icons in the DOM.
This approach offers an advantage over using an <img> tag or via the CSS background-image property, because it allows styling and animating the SVG with CSS.

For example, if the fill or stroke properties of elements in the svg are set to currentColor, they will have the color defined for the containing DOM element. So the color can easily be changed by changing the color style on the svg-icon element.

Installation

npm i @ngneat/svg-icon
npm i @ngneat/svg-generator --save-dev

Icons Preparation

  • Add the icons to src/assets/svg
  • Add an alias to the tsconfig file (optional):
{
  "paths": {
    "@app/svg/*": ["src/app/svg/*"]
  }
}
  • Configure the @ngneat/svg-generator to clean and extract the icons content. Add the following to your package.json file:
{
  "scripts": {
    "prestart": "npm run svg",
    "prebuild": "npm run svg",
    "svg": "svg-generator"
  },
  "svgGenerator": {
    "outputPath": "./src/app/svg",
    "srcPath": "./src/assets/svg",
    "svgoConfig": {
      "plugins": [
        "removeDimensions",
        "cleanupAttrs",
        {
          "name": "convertColors",
          "params": {
            "currentColor": true
          }
        }
      ]
    }
  }
}

It can be modified to meet your needs.

  • Add the outputPath to your gitignore file
  • Run npm run svg

Icons Rendering

Use the provideSvgIcons to register the icons:

import { provideSvgIcons } from '@ngneat/svg-icon';
import { settingsIcon } from '@app/svg/settings';

bootstrapApplication(AppComponent, {
  providers: [provideSvgIcons([settingsIcon])],
});

Now we can import the standalone SvgIconComponent and use the svg-icon component:

import { SvgIconComponent } from '@ngneat/svg-icon';

@Component({
  imports: [SvgIconComponent],
  template: `
    <svg-icon key="settings"></svg-icon>

    <svg-icon key="settings" color="hotpink" fontSize="40px"></svg-icon>
  `,
})
export class FooComponent {}

Note that the key should be striclty typed based on your icons. You can also export the SvgIcons type from the library if you need it.

Register icons locally

In lazy load modules or lazy routes, we can use the provideSvgIcons method, for register icons accessible locally in these modules:

import { dashboardIcon } from '@app/svg/dashboard';
import { userIcon } from '@app/svg/user';
import { provideSvgIcons } from '@ngneat/svg-icon';

@NgModule({
  declarations: [DashboardComponent],
  providers: [provideSvgIcons([userIcon])],
  imports: [DashboardRoutingModule],
})
export class DashboardModule {}

// OR in a Route def
{
  path: 'dashboard',
  providers: [provideSvgIcons([userIcon])],
  component: DashboardPageComponent
}

Note that we’re NOT using a barrel file (i.e index.ts). This will make sure we only load the SVG files we use in the current module.

Webpack Plugin

To make the process more seamless, the library provides a Webpack plugin you can use to automate the extracting process:

const { SvgGeneratorWebpackPlugin } = require('@ngneat/svg-generator/webpack-plugin');

{
  plugins: [
    new SvgGeneratorWebpackPlugin({
      watch: !isProd,
      srcPath: './src/assets/svg',
      outputPath: './src/app/svg',
      svgoConfig: {
        plugins: ['removeDimensions'],
      },
    }),
  ];
}

Group Icons

There are cases where we want to group multiple SVG icons. For example, we might have a notifications feature, and we need to load SVG icons such as Slack, Email, etc.

In such cases, create a unique directory, and put the related icons inside it. For example:

home.svg
user.svg
/notifications
 - slack.svg
 - email.svg

This will create a notifications folder with a barrel file that export the SVG icons inside the folder under a const named ${folderName}Icons:

import { notificationsIcons } from '@app/svg/notifications';

@NgModule({
  providers: [provideSvgIcons(notificationsIcons)],
})
export class NotificationsModule {}

Icon Sizing

To control the SVG size, we use the font-size property as described in this article.
You also have the option to pass fixed sizes and use them across the application:

import { provideSvgIconsConfig } from '@ngneat/svg-icon';

bootstrapApplication(AppComponent, {
  providers: [
    provideSvgIconsConfig({
      sizes: {
        xs: '10px',
        sm: '12px',
        md: '16px',
        lg: '20px',
        xl: '25px',
        xxl: '30px',
      },
      defaultSize: 'md',
      icons,
    }),
  ],
});

They are used in the size input:

<svg-icon key="settings" size="lg"></svg-icon>

Inputs

@Input() key: string;
@Input() size: string;
@Input() fontSize: string;
@Input() color: string;
@Input() width: string | number;
@Input() height: string | number;
@Input() noShrink: boolean;

SvgIconRegistry

You can inject the SvgIconRegistry, and get existing SVG icons or register new ones:

import { SvgIconRegistry } from '@ngneat/svg-icon';

interface Icon {
  name: string;
  data: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  constructor(private registry: SvgIconRegistry) {
    registry.register([Icon, Icon, Icon]);
    registry.register(Icon);
    registry.get(name);
    registry.getAll();
  }
}

You can also use the injectRegisterIcons method to register icons using the new inject API:

import { injectRegisterIcons } from '@ngneat/svg-icon';

interface Icon {
  name: string;
  data: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  constructor() {
    injectRegisterIcons([Icon, Icon, Icon]);
  }
}

Missing Icon

You can define missingIconFallback which will be used if icon is not found in registry:

import { provideSvgIconsConfig } from '@ngneat/svg-icon';
import { unknownIcon } from '@app/svg/unknown';

bootstrapApplication(AppComponent, {
  providers: [
    provideSvgIconsConfig({
      missingIconFallback: unknownIcon,
    }),
  ],
});

Custom config file

The svgGenerator config object is placed by default in your main package.json.

It can also be placed in any location supported by the Cosmiconfig library such as a custom .svgGeneratorrc.json file.

The config object is looked for in the project root directory by default.

If your config object is located in another directory, you can specify it through the --config-dir option of the svg CLI: npm run svg --config-dir=/your/custom/dir/where/the/config/is/located. The config object will then be looked for in all valid Cosmiconfig library locations starting from that directory and going up the directory tree until a config is found.