DEV Community

Cover image for Use any icon library in your Ember app without an addon
Ignace Maes
Ignace Maes

Posted on

Use any icon library in your Ember app without an addon

What if you didn't need a dedicated Ember addon to use icons. Since Ember runs on standard build tooling (Vite or webpack), you can tap into unplugin-icons directly. It gives you on-demand access to 200,000+ icons from 150+ icon sets, all loaded as components. Only the icons you import end up in your bundle. It works with both Vite and webpack, so it covers both modern and classic Ember setups.

The Ember compiler landed in unplugin-icons v0.22. Here's how to set it up.

1. Install the dependencies

You need two things: the plugin itself and at least one icon set. Lucide is a solid default (clean, consistent, MIT-licensed), but you can pick whatever you want from Iconify's collection.

pnpm add -D unplugin-icons @iconify-json/lucide
Enter fullscreen mode Exit fullscreen mode

Want multiple sets? Install them all:

pnpm add -D unplugin-icons @iconify-json/lucide @iconify-json/simple-icons
Enter fullscreen mode Exit fullscreen mode

2. Configure your build tool

Vite (recommended)

If your app uses @embroider/vite, open vite.config.mjs and add the plugin:

import Icons from 'unplugin-icons/vite';

export default defineConfig({
  plugins: [
    ember(),
    // ... your other plugins
    Icons({ compiler: 'ember' }),
  ],
});
Enter fullscreen mode Exit fullscreen mode

Webpack

If your app uses Embroider with webpack (or classic ember-auto-import), add the plugin to your ember-cli-build.js:

const Icons = require('unplugin-icons/webpack');

module.exports = function (defaults) {
  const app = new EmberApp(defaults, {
    // ...
  });

  return require('@embroider/compat').compatBuild(app, require('@embroider/webpack').Webpack, {
    packagerOptions: {
      webpackConfig: {
        plugins: [Icons({ compiler: 'ember' })],
      },
    },
  });
};
Enter fullscreen mode Exit fullscreen mode

Vite is the recommended path forward for Ember apps. If you're starting a new project, go with Vite.

3. Use icons in your components

Import any icon using the ~icons/{collection}/{icon-name} convention and drop it into your template like any other component:

import Search from '~icons/lucide/search';
import ChevronDown from '~icons/lucide/chevron-down';
import GithubIcon from '~icons/simple-icons/github';

<template>
  <button type="button">
    <Search />
    Search...
    <ChevronDown />
  </button>

  <a href="https://github.com">
    <GithubIcon />
  </a>
</template>
Enter fullscreen mode Exit fullscreen mode

Icons render as inline SVGs. They inherit currentColor by default, so they follow your text color. Size them with font-size, width/height, or a utility class.

import Check from '~icons/lucide/check';

<template>
  {{! Sized via Tailwind }}
  <Check class="size-4" />

  {{! Sized via inline style }}
  <Check style="width: 2em; height: 2em;" />
</template>
Enter fullscreen mode Exit fullscreen mode

Finding icon names

Browse icons at icones.js.org or icon-sets.iconify.design. The collection name and icon name map directly to the import path:

  • Collection: lucide, icon: arrow-right~icons/lucide/arrow-right
  • Collection: simple-icons, icon: emberdotjs~icons/simple-icons/emberdotjs
  • Collection: mdi, icon: account-box~icons/mdi/account-box

If you use VS Code, install the Iconify IntelliSense extension. It gives you inline previews and autocomplete for icon names.

Custom SVG icons

You can load your own SVGs too. Use FileSystemIconLoader to point at a directory:

import { FileSystemIconLoader } from 'unplugin-icons/loaders';

Icons({
  compiler: 'ember',
  customCollections: {
    custom: FileSystemIconLoader('./app/assets/icons'),
  },
});
Enter fullscreen mode Exit fullscreen mode

Then import them the same way:

import Logo from '~icons/custom/logo';

<template>
  <Logo />
</template>
Enter fullscreen mode Exit fullscreen mode

Make sure your SVGs use currentColor for fills/strokes if you want them to adapt to text color.

TypeScript

Add unplugin-icons/types/ember to the types array in your tsconfig.json:

{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/ember"
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

This gives you proper module declarations for ~icons/* imports so TypeScript stops complaining.

That's all

Same dependencies, same imports, same compiler: 'ember'. Whether you're on Vite or webpack, the DX is identical. No icon fonts, no sprite sheets, no build scripts. The icons are tree-shaken automatically: if you don't import it, it doesn't exist in your bundle.

The full list of supported icon sets lives at icones.js.org.

Top comments (0)