Git Product home page Git Product logo

unplugin-icons's Introduction

unplugin-icons

NPM version

Access thousands of icons as components on-demand universally.

Features

  • 🌏 Universal
    • 🤹 Any icon sets - ~150 popular sets with over 200,000 icons, logos, emojis, etc. Powered by Iconify.
    • 📦 Major build tools - Vite, Webpack, Rollup, Nuxt, etc. Powered by unplugin.
    • 🚀 Major frameworks - Vanilla, Web Components, React, Vue 3, Vue 2, Solid, Svelte, and more. Contribute.
    • 🍱 Any combinations of them!
  • ☁️ On-demand - Only bundle the icons you really use, while having all the options.
  • 🖨 SSR / SSG friendly - Ship the icons with your page, no more FOUC.
  • 🌈 Stylable - Change size, color, or even add animations as you would with styles and classes.
  • 📥 Custom icons - load your custom icons to get universal integrations at ease.
  • 📲 Auto Importing - Use icons as components directly in your template.
  • 🦾 TypeScript support.
  • 🔍 Browse Icons

   💡 Story behind this tool: Journey with Icons Continues - a blog post by Anthony   

vite-plugin-icons has been renamed to unplugin-icons, see the migration guide

Usage

Import icons names with the convention ~icons/{collection}/{icon} and use them directly as components. Auto importing is also possible.

React
import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'

function App() {
  return (
    <div>
      <IconAccessibility />
      <IconAccountBox style={{ fontSize: '2em', color: 'red' }} />
    </div>
  )
}
Vue
<script setup>
import IconAccessibility from '~icons/carbon/accessibility'
import IconAccountBox from '~icons/mdi/account-box'
</script>

<template>
  <icon-accessibility/>
  <icon-account-box style="font-size: 2em; color: red"/>
</template>

Install

Plugin

npm i -D unplugin-icons

Icons Data

We use Iconify as the icons data source (supports 100+ iconsets).

You have two ways to install them:

Install Full Collection
npm i -D @iconify/json

@iconify/json (~120MB) includes all the iconsets from Iconify so you can install once and use any of them as you want (only the icons you actually use will be bundle into the production build).

Install by Icon Set

If you only want to use a few of the icon sets and don't want to download the entire collection, you can also install them individually with @iconify-json/[collection-id]. For example, to install Material Design Icons, you can do:

npm i -D @iconify-json/mdi

To boost your workflow, it's also possible to let unplugin-icons handle that installation by enabling the autoInstall option.

Icons({
  // experimental
  autoInstall: true,
})

It will install the icon set when you import them. The right package manager will be auto-detected (npm, yarn or pnpm).

Examples

You can play online with the examples in this repo in StackBlitz, see playgrounds page.

Fork any of the online examples and reproduce the issue you're facing, then share the link with us.

Configuration

Build Tools
Vite
// vite.config.ts
import Icons from 'unplugin-icons/vite'

export default defineConfig({
  plugins: [
    Icons({ /* options */ }),
  ],
})


Rollup
// rollup.config.js
import Icons from 'unplugin-icons/rollup'

export default {
  plugins: [
    Icons({ /* options */ }),
  ],
}


Webpack
// webpack.config.js
module.exports = {
  /* ... */
  plugins: [
    require('unplugin-icons/webpack').default({ /* options */ }),
  ],
}


Nuxt

Nuxt 2 and Nuxt Bridge

// nuxt.config.js
export default {
  buildModules: [
    ['unplugin-icons/nuxt', { /* options */ }],
  ],
}

Nuxt 3

// nuxt.config.js
export default defineNuxtConfig({
  modules: [
    ['unplugin-icons/nuxt', { /* options */ }]
  ],
})

See the Nuxt example for a working example project.


Vue CLI
// vue.config.js
module.exports = {
  configureWebpack: {
    plugins: [
      require('unplugin-icons/webpack').default({ /* options */ }),
    ],
  },
}

You can also rename the Vue configuration file to vue.config.mjs and use static import syntax (you should use latest @vue/cli-service ^5.0.8):

// vue.config.mjs
import Icons from 'unplugin-icons/webpack'

export default {
  configureWebpack: {
    plugins: [
      Icons({ /* options */ }),
    ],
  },
}


SvelteKit

The unplugin-icons plugin should be configured in the vite.config.js configuration file:

// vite.config.js
import { defineConfig } from 'vite'
import { sveltekit } from '@sveltejs/kit/vite'
import Icons from 'unplugin-icons/vite'

export default defineConfig({
  plugins: [
    sveltekit(),
    Icons({
      compiler: 'svelte',
    })
  ]
})

Check instructions in the Frameworks -> Svelte section below if you faced module import errors.

See the SvelteKit example for a working example project.


Svelte + Vite

Svelte support requires the @sveltejs/vite-plugin-svelte plugin:

npm i -D @sveltejs/vite-plugin-svelte

The unplugin-icons plugin should be configured in the vite.config.js configuration file:

// vite.config.js
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import Icons from 'unplugin-icons/vite'

export default defineConfig({
  plugins: [
    svelte(),
    Icons({
      compiler: 'svelte',
    }),
  ],
})

Check instructions in the Frameworks -> Svelte section below if you faced module import errors.

See the Svelte + Vite example for a working example project.


Next.js

The unplugin-icons plugin should be configured on next.config.js configuration file:

// next.config.js
/** @type {import('next').NextConfig} */
module.exports = {
  reactStrictMode: true,
  webpack(config) {
    config.plugins.push(
      require('unplugin-icons/webpack').default({
        compiler: 'jsx',
        jsx: 'react'
      })
    )

    return config
  },
}

You can also rename the Next configuration file to next.config.mjs and use static import syntax:

// next.config.mjs
import Icons from 'unplugin-icons/webpack'

/** @type {import('next').NextConfig} */
export default {
  reactStrictMode: true,
  webpack(config) {
    config.plugins.push(
      Icons({
        compiler: 'jsx',
        jsx: 'react'
      })
    )

    return config
  }
}

Check instructions in the Frameworks -> React section below if you faced module import errors.

⚠️ Warning: to import an icon is necessary to explicitly add the .jsx extension to the import path, so that Next.js knows how to load it, by example:

import IconArrowRight from '~icons/dashicons/arrow-right.jsx';
                                                     // ^-- write `.jsx` to avoid
                                                     // https://github.com/antfu/unplugin-icons/issues/103
// ...some code later
<IconArrowRight />

See the Next.js example for a working example project.


esbuild
// esbuild.config.js
import { build } from 'esbuild'
import Icons from 'unplugin-icons/esbuild'

build({
  /* ... */
  plugins: [
    Icons({
      /* options */
    }),
  ],
})


Astro
// astro.config.mjs
import { defineConfig } from 'astro/config'
import Icons from 'unplugin-icons/vite'

// https://astro.build/config
export default defineConfig({
  vite: {
    plugins: [
      Icons({
        compiler: 'astro',
      }),
    ],
  },
})

See the Astro example for a working example project.


Frameworks
Vue 3 / Vue 2.7+

Vue 3 / Vue 2.7+ support requires peer dependency @vue/compiler-sfc:

npm i -D @vue/compiler-sfc
Icons({ compiler: 'vue3' })

Type Declarations

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/vue",
    ]
  }
}

See the Vue 3 example for a working example project.


Vue 2 (only for versions < 2.7)

Vue 2 support requires peer dependency vue-template-compiler:

npm i -D vue-template-compiler
Icons({ compiler: 'vue2' })

Type Declarations

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/vue",
    ]
  }
}

See the Vue 2 example for a working example project.


React

JSX support requires peer dependency @svgr/core and its plugin @svgr/plugin-jsx:

npm i -D @svgr/core @svgr/plugin-jsx
Icons({ compiler: 'jsx', jsx: 'react' })

Type Declarations

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/react",
    ]
  }
}

See the React example for a working example project.


Preact

JSX support requires peer dependency @svgr/core and its plugin @svgr/plugin-jsx:

npm i -D @svgr/core @svgr/plugin-jsx
Icons({ compiler: 'jsx', jsx: 'preact' })

Type Declarations

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/preact",
    ]
  }
}

See the Preact example for a working example project.


Solid
Icons({ compiler: 'solid' })

Type Declarations

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/solid",
    ]
  }
}

See the Solid example for a working example project.


Svelte
Icons({ compiler: 'svelte' })

Type Declarations

For SvelteKit, in the src/app.d.ts file:

import 'unplugin-icons/types/svelte'

For Svelte + Vite, in the src/vite-env.d.ts file:

/// <reference types="svelte" />
/// <reference types="vite/client" />
/// <reference types="unplugin-icons/types/svelte" />

If you're still using Svelte 3, replace the reference to use Svelte 3:

/// <reference types="svelte" />
/// <reference types="vite/client" />
/// <reference types="unplugin-icons/types/svelte3" />

See the Svelte example for a working example project.


Astro

Type Declarations

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/astro",
    ]
  }
}

See the Astro example for a working example project.


Qwik

Qwik support requires peer dependency @svgx/core:

npm i -D @svgx/core
Icons({ compiler: 'qwik' })

Alternatively, you can use jsx compiler, requires peer dependency @svgr/core and its plugin @svgr/plugin-jsx:

npm i -D @svgr/core @svgr/plugin-jsx
Icons({ compiler: 'jsx', jsx: 'qwik' })

Type Declarations

// tsconfig.json
{
  "compilerOptions": {
    "types": [
      "unplugin-icons/types/qwik",
    ]
  }
}

See the Qwik example for a working example project.


Use RAW compiler from query params

From v0.13.2 you can also use raw compiler to access the svg icon and use it on your html templates, just add raw to the icon query param.

For example, using vue3:

<script setup lang='ts'>
import RawMdiAlarmOff from '~icons/mdi/alarm-off?raw&width=4em&height=4em'
import RawMdiAlarmOff2 from '~icons/mdi/alarm-off?raw&width=1em&height=1em'
</script>

<template>
  <!-- raw example -->
  <pre>
    import RawMdiAlarmOff from '~icons/mdi/alarm-off?raw&width=4em&height=4em'
    {{ RawMdiAlarmOff }}
    import RawMdiAlarmOff2 from '~icons/mdi/alarm-off?raw&width=1em&height=1em'
    {{ RawMdiAlarmOff2 }}
  </pre>
  <!-- svg example -->
  <span v-html="RawMdiAlarmOff" />
  <span v-html="RawMdiAlarmOff2" />
</template>

Custom Icons

From v0.11, you can now load your own icons!

From v0.13 you can also provide a transform callback to FileSystemIconLoader.

import { promises as fs } from 'node:fs'

// loader helpers
import { FileSystemIconLoader } from 'unplugin-icons/loaders'

Icons({
  customCollections: {
    // key as the collection name
    'my-icons': {
      account: '<svg><!-- ... --></svg>',
      // load your custom icon lazily
      settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
      /* ... */
    },
    'my-other-icons': async (iconName) => {
      // your custom loader here. Do whatever you want.
      // for example, fetch from a remote server:
      return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())
    },
    // a helper to load icons from the file system
    // files under `./assets/icons` with `.svg` extension will be loaded as it's file name
    // you can also provide a transform callback to change each icon (optional)
    'my-yet-other-icons': FileSystemIconLoader(
      './assets/icons',
      svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
    ),
  },
})

Then use as

import IconAccount from '~icons/my-icons/account'
import IconFoo from '~icons/my-other-icons/foo'
import IconBar from '~icons/my-yet-other-icons/bar'

💡 SVG Authoring Tips:

  • To make your icons color adaptable, set fill="currentColor" or stroke="currentColor" in your SVG.
  • Leave the height and width unspecified, we will set them for you.

Use with Resolver

When using resolvers for auto-importing, you will need to tell it your custom collection names:

IconResolver({
  customCollections: [
    'my-icons',
    'my-other-icons',
    'my-yet-other-icons',
  ],
})

See the Vue 3 + Vite example.

Use Custom External Collection Packages

From version v0.18.3 you can use other packages to load icons from others authors.

WARNING: external packages must include icons.json file with the icons data in IconifyJSON format, which can be exported with Iconify Tools. Check Exporting icon set as JSON package for more details.

For example, you can use an-awesome-collection or @my-awesome-collections/some-collection to load your custom or third party icons:

// loader helpers
import { ExternalPackageIconLoader } from 'unplugin-icons/loaders'

Icons({ customCollections: ExternalPackageIconLoader('my-awesome-collection') })

When using with resolvers for auto-importing, remember you will need to tell it your custom collection names:

IconResolver({
  customCollections: [
    'my-awesome-collection',
  ],
})

You can also combine it with FileSystemIconLoader or with other custom icon loaders:

// loader helpers
import { ExternalPackageIconLoader, FileSystemIconLoader } from 'unplugin-icons/loaders'

Icons({
  customCollections: {
    ...ExternalPackageIconLoader('an-awesome-collection'),
    ...ExternalPackageIconLoader('@my-awesome-collections/some-collection'),
    ...ExternalPackageIconLoader('@my-awesome-collections/some-other-collection'),
    'my-yet-other-icons': FileSystemIconLoader(
      './assets/icons',
      svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
    ),
  },
})

See the Vue 3 + Vite example.

Icon customizer

From v0.13 you can also customize each icon using iconCustomizer configuration option or using query params when importing them.

The query param will take precedence over iconCustomizer and iconCustomizer over configuration.

The iconCustomizer and query params will be applied to any collection, that is, for each icon from custom loader, inlined on customCollections or from @iconify.

For example, you can configure iconCustomizer to change all icons for a collection or individual icons on a collection:

import { promises as fs } from 'node:fs'

// loader helpers
import { FileSystemIconLoader } from 'unplugin-icons/loaders'

Icons({
  customCollections: {
    // key as the collection name
    'my-icons': {
      account: '<svg><!-- ... --></svg>',
      // load your custom icon lazily
      settings: () => fs.readFile('./path/to/my-icon.svg', 'utf-8'),
      /* ... */
    },
    'my-other-icons': async (iconName) => {
      // your custom loader here. Do whatever you want.
      // for example, fetch from a remote server:
      return await fetch(`https://example.com/icons/${iconName}.svg`).then(res => res.text())
    },
    // a helper to load icons from the file system
    // files under `./assets/icons` with `.svg` extension will be loaded as it's file name
    // you can also provide a transform callback to change each icon (optional)
    'my-yet-other-icons': FileSystemIconLoader(
      './assets/icons',
      svg => svg.replace(/^<svg /, '<svg fill="currentColor" '),
    ),
  },
  iconCustomizer(collection, icon, props) {
    // customize all icons in this collection
    if (collection === 'my-other-icons') {
      props.width = '4em'
      props.height = '4em'
    }
    // customize this icon in this collection
    if (collection === 'my-icons' && icon === 'account') {
      props.width = '6em'
      props.height = '6em'
    }
    // customize this @iconify icon in this collection
    if (collection === 'mdi' && icon === 'account') {
      props.width = '2em'
      props.height = '2em'
    }
  },
})

or you can use query params to apply to individual icons:

<script setup lang='ts'>
import MdiAlarmOff from 'virtual:icons/mdi/alarm-off?width=4em&height=4em'
import MdiAlarmOff2 from 'virtual:icons/mdi/alarm-off?width=1em&height=1em'
</script>

<template>
  <!-- width=4em and height=4em -->
  <mdi-alarm-off />
  <!-- width=4em and height=4em -->
  <MdiAlarmOff />
  <!-- width=1em and height=1em -->
  <MdiAlarmOff2 />
</template>

See src/App.vue component and vite.config.ts configuration on vite-vue3 example project.

Global Custom Icon Transformation

From version 0.14.2, when loading your custom icons, you can transform them, for example adding fill attribute with currentColor:

Icons({
  customCollections: {
    // key as the collection name
    'my-icons': {
      account: '<svg><!-- ... --></svg>',
      /* ... */
    },
  },
  transform(svg, collection, icon) {
    // apply fill to this icon on this collection
    if (collection === 'my-icons' && icon === 'account')
      return svg.replace(/^<svg /, '<svg fill="currentColor" ')

    return svg
  },
})

Advanced Custom Icon Set Cleanup

When using this plugin with your custom icons, consider using a cleanup process similar to that done by Iconify for any icons sets. All the tools you need are available in Iconify Tools.

You can check this repo, using unplugin-icons on a SvelteKit project: https://github.com/iconify/tools/tree/main/%40iconify-demo/unplugin-svelte.

Read Cleaning up icons article from Iconify for more details.

Migrate from vite-plugin-icons

package.json

{
  "devDependencies": {
-   "vite-plugin-icons": "*",
+   "unplugin-icons": "^0.7.0",
  }
}

vite.config.json

import Components from 'unplugin-vue-components/vite'
- import Icons, { ViteIconsResolver } from 'vite-plugin-icons'
+ import Icons from 'unplugin-icons/vite'
+ import IconsResolver from 'unplugin-icons/resolver'

export default {
  plugins: [
    Vue(),
    Components({
      resolvers: [
        IconsResolver()
      ],
    }),
    Icons(),
  ],
}

* - imports usage

- import IconComponent from 'virtual:vite-icons/collection/name'
+ import IconComponent from '~icons/collection/name'

You can still use virtual:icons prefix in Vite if you prefer, but it's not yet supported in Webpack, we are unifying it as a workaround in the docs.

Options

You can set default styling for all icons. The following config shows the default values of each option:

Icons({
  scale: 1.2, // Scale of icons against 1em
  defaultStyle: '', // Style apply to icons
  defaultClass: '', // Class names apply to icons
  compiler: null, // 'vue2', 'vue3', 'jsx'
  jsx: 'react', // 'react' or 'preact'
})

Auto Importing

Vue 2 & 3

Use with unplugin-vue-components

For example in Vite:

// vite.config.js
import Vue from '@vitejs/plugin-vue'
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'

export default {
  plugins: [
    Vue(),
    Components({
      resolvers: [
        IconsResolver(),
      ],
    }),
    Icons(),
  ],
}

Then you can use any icons as you want without explicit importing. Only the used icons will be bundled.

<template>
  <i-carbon-accessibility/>
  <i-mdi-account-box style="font-size: 2em; color: red"/>
</template>
React & Solid

Use with unplugin-auto-import

For example in Vite:

// vite.config.js
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import AutoImport from 'unplugin-auto-import/vite'

export default {
  plugins: [
    /* ... */
    AutoImport({
      resolvers: [
        IconsResolver({
          prefix: 'Icon',
          extension: 'jsx',
        }),
      ],
    }),
    Icons({
      compiler: 'jsx', // or 'solid'
    }),
  ],
}

Then you can use any icons with the prefix Icon as you want without explicit importing. Type declarations will be generated on the fly.

export function Component() {
  return (
    <div>
      <IconCarbonApps />
      <IconMdiAccountBox style="font-size: 2em; color: red" />
    </div>
  )
}

Name Conversion

When using component resolver, you have to follow the name conversion for icons to be properly inferred.

{prefix}-{collection}-{icon}

The collection field follows Iconify's collection IDs.

By default, the prefix is set to i while you can customize via config

IconsResolver({
  prefix: 'icon', // <--
})
<template>
  <icon-mdi-account />
</template>

Non-prefix mode is also supported

IconsResolver({
  prefix: false, // <--
  // this is optional, default enabling all the collections supported by Iconify
  enabledCollections: ['mdi'],
})
<template>
  <mdi-account />
</template>

Collection Aliases

When using component resolver, you have to use the name of the collection that can be long or redundant: for example, when using icon-park collection you need to use it like this <icon-icon-park-abnormal />.

You can add an alias for any collection to the IconResolver plugin:

IconsResolver({
  alias: {
    park: 'icon-park',
    fas: 'fa-solid',
    // ...
  }
})

You can use the alias or the collection name, the plugin will resolve both.

Following with the example and configuring the plugin with previous alias entry, you can now use <icon-park-abnormal /> or <icon-icon-park-abnormal />.

Sponsors

This project is part of my Sponsor Program

License

MIT License © 2020-PRESENT Anthony Fu

unplugin-icons's People

Contributors

antfu avatar benmccann avatar chojnicki avatar cyberalien avatar enyo avatar hannoeru avatar ianvs avatar iztsv avatar jfgodoy avatar leizhenpeng avatar likeben avatar mvllow avatar ntnyq avatar orkunkocyigit avatar peter50216 avatar puruvj avatar qq15725 avatar rainmanhhh avatar ralacerda avatar replygirl avatar ryoppippi avatar serialine avatar spa5k avatar sxzz avatar theoephraim avatar tony19 avatar userquin avatar vhscom avatar waleed-kh avatar zyyv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unplugin-icons's Issues

[Question]: How to use icons from string?

When using the icons with strings it's not working in component. How to get it working, please? Sample code -

<template>
    <div>
        <nav class="grid gap-y-8">
            <a
		v-for="item in solutions"
		:key="item.name"
		:href="item.href"
		class="-m-3 p-3 flex items-center rounded-md"
	   >
		<component :is="item.icon" class="flex-shrink-0 h-6 w-6 text-black" aria-hidden="true" />
		<span class="ml-3 text-base font-medium text-gray-200">{{ item.name }}</span>
	   </a>
	</nav>
</div>

<script setup lang="ts">

const solutions = [
	{
		name: 'Item',
		description: 'Go to item',
		href: '#',
		icon: 'heroicons-outline:chart-bar',
	},
	{
		name: 'Item',
		description: 'Go to item',
		href: '#',
		icon: 'heroicons-outline:cursor-click',
	},
];

</script>

Icon names ending in numbers are not working

It appears icons with ending numbers aren't working.

<heroicons-outline-menu-alt-2 />

gets converted to:

/@id/@vite-icons/heroicons-outline/menu-alt2

and of course fails to load without the missing hyphen

`jsx` compiler failing when icon name contains numbers

There are icon names with numbers, not only letters, for example MdiStore24Hour.

The fix is simple, just replacing:

function camel(str: string) {
  return str.replace(/-([a-z])/g, g => g[1].toUpperCase())
}

with

function camel(str: string) {
  return str.replace(/-([a-z0-9])/g, g => g[1].toUpperCase())
}
F:\work\projects\quini\GitHub\antfu\unplugin-icons\examples\vite-preact\unknown: Identifier directly after number. (2:26)
  1 | /* @babel/template */;
> 2 | export default mdiStore-24Hour
    |                          ^
    at Object._raise (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:798:17)
    at Object.raiseWithData (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:791:17)
    at Object.raise (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:752:17)
    at Object.readNumber (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:2578:18)
    at Object.getTokenFromCode (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:2272:14)
    at Object.getTokenFromCode (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:7197:18)
    at Object.getTokenFromCode (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:9934:18)
    at Object.nextToken (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:1750:12)
    at Object.next (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:1656:10)
    at Object.parseExprOp (F:\work\projects\quini\GitHub\antfu\unplugin-icons\node_modules\.pnpm\@[email protected]\node_modules\@babel\parser\lib\index.js:10918:14

imagen

[jsx] scale option is not respected

The JSXCompiler runs the svg through svgr, with the icon: true option. This option sets width and height to 1em, which overrides the values provided from the scale option. I think that option can be removed, since this plugin already sets width and height based on the scale.

Can't load icons with vitepress

Hey with the latest vitepress the icons can't install. Tried both options with no avail. I just get a blank page.

    "vite-plugin-icons": "^0.2.2",
    "vite-plugin-components": "^0.6.12",
    "@iconify/json": "^1.1.306"

Also I can't update vite-plugin-windicss to the latest version and have it work with vitepress. The latest version that works is

    "vite-plugin-windicss": "^0.1.9",
    "vitepress": "^0.12.2"

Thanks for the great work.

Clean symbols

It would be nice to be able to automatically clean some attributes making CSS styling more difficult.

For example (we currently use svgstore):

{
  cleanSymbols: ['stroke', 'fill'],
}

Input:

<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21.48 11C20.7851 10.621 3.47885 0.806646 3.47885 0.806646C2.81248 0.443169 2 0.925483 2 1.68454V8.65973C2 9.69991 2.79733 10.5664 3.83391 10.6528L13.5017 11.4585C13.7834 11.4819 14 11.7174 14 12V12C14 12.2826 13.7834 12.5181 13.5017 12.5415L3.83391 13.3472C2.79732 13.4336 2 14.3001 2 15.3403V22.3155C2 23.0745 2.81248 23.5568 3.47885 23.1934C3.47885 23.1934 20.7851 13.379 21.48 13C22.1749 12.621 22.1749 11.379 21.48 11Z" fill="black"/>
</svg>

Output:

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M21.48 11C20.7851 10.621 3.47885 0.806646 3.47885 0.806646C2.81248 0.443169 2 0.925483 2 1.68454V8.65973C2 9.69991 2.79733 10.5664 3.83391 10.6528L13.5017 11.4585C13.7834 11.4819 14 11.7174 14 12V12C14 12.2826 13.7834 12.5181 13.5017 12.5415L3.83391 13.3472C2.79732 13.4336 2 14.3001 2 15.3403V22.3155C2 23.0745 2.81248 23.5568 3.47885 23.1934C3.47885 23.1934 20.7851 13.379 21.48 13C22.1749 12.621 22.1749 11.379 21.48 11Z"/>
</svg>

dynamic icons?

Say you have const providers = ref(['google','facebook']) and what to load icons based on the names. How could you do that with this library? For static icons its working great!

Correct usage with heroicons + dynamic component syntax

Howdy! Still learning the ropes, and I promise I've read the documentation, so I promise I've spent a bit of time reading the documentation on both vite-plugin-icons + iconify...

Current setup - Using Vitesse boilerplate, no major changes to icons or components plugins configs:

    ViteComponents({
      // allow auto load markdown components under `./src/components/`
      extensions: ['vue', 'md'],

      // allow auto import and register components used in markdown
      customLoaderMatcher: id => id.endsWith('.md'),

      // generate `components.d.ts` for ts support with Volar
      globalComponentsDeclaration: true,

      // auto import icons
      customComponentResolvers: [
        HeadlessUiResolver(),
        ViteIconsResolver({
          componentPrefix: '',
          // enabledCollections: ['hero', 'mdi', 'carbon'],
        }),
      ],
    }),

    // https://github.com/antfu/vite-plugin-icons
    ViteIcons(),

In my Home Layout File /src/layouts/home.vue, I am working with a simple v-for loop. There is the following code:

<component :is="item.icon" class="mr-4 flex-shrink-0 h-6 w-6 text-indigo-300" aria-hidden="true" />

And I pass in an array of objects that look like this:

const navigation = [
  { name: 'Dashboard', href: '#', icon: 'heroicons-outline-x', current: true },
  { name: 'Team', href: '/hi/Armen', icon: 'heroicons-outline-home', current: false },
  { name: 'Projects', href: '#', icon: 'heroicons-outline:home', current: false },
  { name: 'Calendar', href: '#', icon: 'heroicons-outline:home', current: false },
  { name: 'Documents', href: '#', icon: 'heroicons-outline:home', current: false },
  { name: 'Reports', href: '#', icon: 'heroicons-outline:home', current: false },
]

Neither heroicons-outline-* or heroicons-outline:* appear to work.

I also tried this approach, but kept getting the following error --> Module '"virtual:vite-icons/*"' has no exported member 'MenuAlt2Icon'. Did you mean to use 'import MenuAlt2Icon from "virtual:vite-icons/*"' instead?ts(2614)

// import {
//   IconBellIcon,
//   IconCalendarIcon,
//   IconChartBarIcon,
//   FolderIcon,
//   HomeIcon,
//   InboxIcon,
//   MenuAlt2Icon,
//   UsersIcon,
//   XIcon,
// } from 'virtual:vite-icons/heroicons/outline'

I'm sure that whatever I'm doing wrong is probably something simple/stupid, but I'd appreciate any guidance you might be able to provide.

Thank you!

Failed to resolve import "vue"

This is related to #2

Here is the example repo.

git clone https://github.com/nandordudas/vite-plugin-icons
cd vite-plugin-icons
yarn # or pnpm i
yarn add -D @iconify/json
DEBUG=* yarn dev

connect:dispatcher <anonymous>  : /@vite-icons/mdi/alarm-off +0ms
11:34:28 AM [vite] Internal server error:
  Plugin: vite:imports
  File: /@vite-icons/mdi/alarm-off
  1  |  import { createVNode as _createVNode, openBlock as _openBlock, createBlock as _createBlock } from "vue"
     |                                                                                                     ^
  2  |  
  3  |  const _hoisted_1 = {
  Error: Failed to resolve import "vue". Does the file exist?
      at TransformContext.error (/.../vite-plugin-icons/node_modules/vite/dist/node/chunks/dep-7bace6f3.js:59717:50)
      at TransformContext.transform (/.../vite-plugin-icons/node_modules/vite/dist/node/chunks/dep-7bace6f3.js:53118:30)
      at processTicksAndRejections (node:internal/process/task_queues:93:5)
      at async Object.transform (/.../vite-plugin-icons/node_modules/vite/dist/node/chunks/dep-7bace6f3.js:59907:30)
      at async transformRequest (/.../vite-plugin-icons/node_modules/vite/dist/node/chunks/dep-7bace6f3.js:66142:29)
      at async /.../vite-plugin-icons/node_modules/vite/dist/node/chunks/dep-7bace6f3.js:66229:32
  vite:time 30ms  /@vite-icons/mdi/alarm-off +32ms

Node: v15.5.1
OS: Manjaro Linux x86_64

Error loading custom Icons

Hi, I'm having this error when trying to reproduce vite + vue3 example

[vite] Internal server error: Cannot read property 'icons' of null
      at Collection.getIconData (C:\Users\kmilo\Desktop\Devitall\dentos\frontend\node_modules\.pnpm\@[email protected]\node_modules\@iconify\json-tools\src\collection.js:461:18)
      at getBuiltinIcon (C:\Users\kmilo\Desktop\Devitall\dentos\frontend\node_modules\.pnpm\[email protected]_954f950b29577c0f46930e88ab1c74d1\node_modules\unplugin-icons\dist\chunk-3NPAQMBG.js:162:18)
      at getIcon (C:\Users\kmilo\Desktop\Devitall\dentos\frontend\node_modules\.pnpm\[email protected]_954f950b29577c0f46930e88ab1c74d1\node_modules\unplugin-icons\dist\chunk-3NPAQMBG.js:185:20)
      at processTicksAndRejections (internal/process/task_queues.js:95:5)
      at async generateComponent (C:\Users\kmilo\Desktop\Devitall\dentos\frontend\node_modules\.pnpm\[email protected]_954f950b29577c0f46930e88ab1c74d1\node_modules\unplugin-icons\dist\chunk-3NPAQMBG.js:194:13)

OS => Windows 10
dependencies =>

"unplugin-auto-import": "^0.2.6",
    "unplugin-icons": "^0.11.2",
    "unplugin-vue-components": "^0.15.1",
    "vite": "^2.5.7",

icon folder =>
image
vite.config =>

Components({
      directoryAsNamespace: true,
      dirs: ['src/components/FormInput', 'src/components/Common', 'src/components'],

      extensions: ['vue'],

      dts: true,

      include: [/\.vue$/, /\.vue\?vue/],

      resolvers: [
        IconsResolver({
          componentPrefix: '',
          customCollections: ['custom'],
        }),
      ],
      exclude: ['src/pages'],
    }),

    Icons({
      compiler: 'vue3',
      customCollections: {
        custom: FileSystemIconLoader('assets/custom-a'),
      },
    }),

import in component =>

<custom-menu-arrow />

Please, some help if I'm doing something wrong, I really like this tool
Thanks

Custom Icons

This is great, I've tried using the vscode-iconify with Vitesse and the DX is super good, I don't think I'll want to go back to the older days!

Which raises the following question: Is it possible to configure custom svgs to be loaded using the same system? I know since the icons are my own, I can just pack them in the project or create my own component to load them (which is what I've been doing so far). But it'd be great to be able of using the same affordances as the other icons, like seeing the icon preview in vscode and such.

Interference with components starting with "feather"

<feathers-vuex-pagination />, which comes from Feathers-Vuex is not able to load due to a conflict with feather-icons. With the latest release of vite-plugins-icons and vite-plugin-components, I am getting the following error message, which prevents app load:

Screen Shot 2021-07-09 at 7 28 15 AM

I'm using the Vitesse template with the default config for vite-plugin-components and vite-plugin-icons.

Icons aren't aligned correctly

Using the icons via the plugin and comparing them to the pasted in SVG, you can see the vertical alignment is wrong.

See

<i-tabler:arrow-narrow-left
	class="w-5 h-5"
/>
<svg
	xmlns="http://www.w3.org/2000/svg"
	aria-hidden="true"
	role="img"
	class="w-5 h-5"
	width="32"
	height="32"
	preserveAspectRatio="xMidYMid meet"
	viewBox="0 0 24 24"
>
	<g
		class="icon-tabler"
		fill="none"
		stroke="currentColor"
		stroke-width="2"
		stroke-linecap="round"
		stroke-linejoin="round"
	>
		<path d="M5 12h14" />
		<path d="M5 12l4 4" />
		<path d="M5 12l4-4" />
	</g>
</svg>

The only added part is the width and height classes.

See image for reference.
The latter arrow (direct SVG) is aligned correctly with the text, whereas the plugin icon is a little too high. I tried with a couple of different icon sets, so it's not just this specific icon.

Vue 3 - CLI Example

Can you please provide an example project that is built using the vue cli with vue 3?

I tried using the vue 2 cli as a guide but I was unsuccessful because of

This dependency was not found:
* ~icons/mdi/account-box in ....

Add icons dynamically

Hi, awesome work with this plugins man, enjoying a lot playing around with vueuse and this one.

Which would be the approach to dynamically insert icons? Let's say I have a menu metadata in a js object and icon is one of the properties.

One option I guess would be to use <component :is="menuitem.icon"> where icon: IconAccountBox .

Would make sense to add a component <icon :name="carbon-icon" /> to the repo?

Build fail

I updated the lib to be able to use Vite 2 and now, dev works fine but builds fail with an issue.
I use the manual import way e.g import CarbonArrowLeft from '/@vite-icons/carbon/arrow-left.vue' and then use it like this <carbon-arrow-left />

Here is the error when building

[vite]: Rollup failed to resolve import "vue" from "../../../../@vite-icons/carbon/arrow-left".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`rollupInputOptions.external`
error during build:
Error: [vite]: Rollup failed to resolve import "vue" from "../../../../@vite-icons/carbon/arrow-left".
This is most likely unintended because it can break your application at runtime.
If you do want to externalize this module explicitly add it to
`rollupInputOptions.external`
    at onRollupWarning (/Users/xyz/project/node_modules/vite/dist/node/chunks/dep-eb5d6c40.js:47866:15)
    at Object.onwarn (/Users/xyz/project/node_modules/vite/dist/node/chunks/dep-eb5d6c40.js:47753:17)
    at Object.onwarn (/Users/xyz/project/node_modules/rollup/dist/shared/rollup.js:19525:20)
    at ModuleLoader.handleResolveId (/Users/xyz/project/node_modules/rollup/dist/shared/rollup.js:18435:26)
    at /Users/xyz/project/node_modules/rollup/dist/shared/rollup.js:18402:22
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Promise.all (index 0)
    at async ModuleLoader.fetchStaticDependencies (/Users/xyz/project/node_modules/rollup/dist/shared/rollup.js:18400:34)
    at async Promise.all (index 0)
    at async ModuleLoader.fetchModule (/Users/xyz/project/node_modules/rollup/dist/shared/rollup.js:18377:9)

My Vite config:

//vite.config.ts
import Vue from '@vitejs/plugin-vue'
import ViteIcons from 'vite-plugin-icons'
import ViteComponents from 'vite-plugin-components'
import { UserConfig } from 'vite'

const config: UserConfig = {
  plugins: [
    Vue(),

    // https://github.com/antfu/vite-plugin-components
    ViteComponents({
      dirs: ['./src/components', './src/layouts'],
    }),

    // https://github.com/antfu/vite-plugin-icons
    ViteIcons(),
  ],
}

export default config

[vite] Internal server error: Dynamic require of "@svgr/core" is not supported

I'm trying to use this package with vite and react, and I've followed the readme but I'm getting the following error during build:

[vite] Internal server error: Dynamic require of "@svgr/core" is not supported

This seems to be triggered from https://github.com/antfu/unplugin-icons/blob/038cf0e5431ff0f4889f5f150b18e74f19ebdced/src/core/compilers/jsx.ts#L6

Relevant parts of my vite.config.js:

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

export default defineConfig({
  plugins: [
    Icons({
      compiler: 'jsx',
      jsx: 'react',
      customCollections: {
        myproject: FileSystemIconLoader('./src/assets/icons'),
      },
    }),
  ],
});

any plans to support dynamic components ?

I have a use case where I have a list of objects that contains the icon information so I tried using:

<component :is="`i-${icon}`" />

but no luck and quite frankly I am not sure if it is even possible.

Failing to load icons when not using auto-discovery

Hi!

I updated my existing application to the latest Vite (beta.29 -> 2.0.1) and vite-plugin-icons (0.2.1 -> 0.2.2) versions. Since then, the plugin fails to load the icons:

Log
vite:config bundled config file loaded in 323ms +0ms
vite:config using resolved config: {
vite:config   plugins: [
vite:config     'vite:pre-alias',
vite:config     'alias',
vite:config     'vite:dynamic-import-polyfill',
vite:config     'vite:resolve',
vite:config     'vite:html',
vite:config     'vite:css',
vite:config     'vite:esbuild',
vite:config     'vite:json',
vite:config     'vite:wasm',
vite:config     'vite:worker',
vite:config     'vite:asset',
vite:config     'vite:vue',
vite:config     'vite:define',
vite:config     'vite:css-post',
vite:config     'vite-plugin-icons',
vite:config     'vite:client-inject',
vite:config     'vite:import-analysis'
vite:config   ],
vite:config   server: {},
vite:config   define: { __VUE_OPTIONS_API__: true, __VUE_PROD_DEVTOOLS__: false },
vite:config   ssr: { external: [ 'vue', '@vue/server-renderer' ] },
vite:config   configFile: 'G:/dev/projekte/vite-icon-example/vite.config.js',
vite:config   inlineConfig: {
vite:config     root: undefined,
vite:config     base: undefined,
vite:config     mode: undefined,
vite:config     configFile: undefined,
vite:config     logLevel: undefined,
vite:config     clearScreen: undefined,
vite:config     server: {}
vite:config   },
vite:config   root: 'G:/dev/projekte/vite-icon-example',
vite:config   base: '/',
vite:config   resolve: { dedupe: undefined, alias: [ [Object] ] },
vite:config   publicDir: 'G:\\dev\\projekte\\vite-icon-example\\public',
vite:config   command: 'serve',
vite:config   mode: 'development',
vite:config   isProduction: false,
vite:config   optimizeCacheDir: 'G:\\dev\\projekte\\vite-icon-example\\node_modules\\.vite',
vite:config   build: {
vite:config     target: [ 'es2019', 'edge16', 'firefox60', 'chrome61', 'safari11' ],
vite:config     polyfillDynamicImport: true,
vite:config     outDir: 'dist',
vite:config     assetsDir: 'assets',
vite:config     assetsInlineLimit: 4096,
vite:config     cssCodeSplit: true,
vite:config     sourcemap: false,
vite:config     rollupOptions: {},
vite:config     commonjsOptions: { include: [Array], extensions: [Array] },
vite:config     minify: 'terser',
vite:config     terserOptions: {},
vite:config     cleanCssOptions: {},
vite:config     write: true,
vite:config     emptyOutDir: null,
vite:config     manifest: false,
vite:config     lib: false,
vite:config     ssr: false,
vite:config     ssrManifest: false,
vite:config     brotliSize: true,
vite:config     chunkSizeWarningLimit: 500
vite:config   },
vite:config   env: { BASE_URL: '/', MODE: 'development', DEV: true, PROD: false },
vite:config   assetsInclude: [Function: assetsInclude],
vite:config   logger: {
vite:config     hasWarned: false,
vite:config     info: [Function: info],
vite:config     warn: [Function: warn],
vite:config     error: [Function: error],
vite:config     clearScreen: [Function: clearScreen]
vite:config   },
vite:config   createResolver: [Function: createResolver]
vite:config } +9ms
vite:deps Crawling dependencies using entries:
vite:deps   G:/dev/projekte/vite-icon-example/index.html +0ms
vite:resolve 1ms   /src/main.js -> G:/dev/projekte/vite-icon-example/src/main.js +0ms
vite:resolve 7ms   vue -> G:/dev/projekte/vite-icon-example/node_modules/vue/dist/vue.runtime.esm-bundler.js +14ms
vite:resolve 1ms   ./App.vue -> G:/dev/projekte/vite-icon-example/src/App.vue +2ms
vite:resolve 3ms   /@vite-icons/carbon/accessibility.vue -> @vite-icons/carbon/accessibility +6ms
vite:resolve 1ms   ./components/HelloWorld.vue -> G:/dev/projekte/vite-icon-example/src/components/HelloWorld.vue +2ms
> html:G:/dev/projekte/vite-icon-example/src/App.vue: error: File could not be loaded: html:@vite-icons/carbon/accessibility
  2  import IconAccessibility from '/@vite-icons/carbon/accessibility.vue'
                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error when starting dev server:
Error: Build failed with 1 error:
html:G:/dev/projekte/vite-icon-example/src/App.vue:2:30: error: File could not be loaded: html:@vite-icons/carbon/accessibility
  at failureErrorWithLog (G:\dev\projekte\vite-icon-example\node_modules\esbuild\lib\main.js:1170:15)
  at buildResponseToResult (G:\dev\projekte\vite-icon-example\node_modules\esbuild\lib\main.js:906:32)
  at G:\dev\projekte\vite-icon-example\node_modules\esbuild\lib\main.js:1001:20
  at G:\dev\projekte\vite-icon-example\node_modules\esbuild\lib\main.js:553:9
  at handleIncomingPacket (G:\dev\projekte\vite-icon-example\node_modules\esbuild\lib\main.js:642:9)
  at Socket.readFromStdout (G:\dev\projekte\vite-icon-example\node_modules\esbuild\lib\main.js:520:7)
  at Socket.emit (events.js:315:20)
  at addChunk (_stream_readable.js:295:12)
  at readableAddChunk (_stream_readable.js:271:9)
  at Socket.Readable.push (_stream_readable.js:212:10)

Link to repro: https://github.com/timozander/vite-icon-bug-repro

resolveId is called, however, then Vite seems to ignore your load() function and passes it directly to esbuild. Changing the mode from post to pre fixes this. However, I do not know if this would impact the auto-loading functionality

Error: Cannot find module '@iconify/json'

I just installed it with npm and added:
import IconAccessibility from "/@vite-icons/carbon/accessibility.vue";
Now I get:

failed to load config from C:\dev\repositories\BettIlias\Frontend\vite.config.ts
error when starting dev server:
Error: Cannot find module '@iconify/json'
Require stack:
- C:\dev\repositories\BettIlias\Frontend\node_modules\.pnpm\[email protected]_@[email protected]\node_modules\vite-plugin-icons\dist\index.js
- C:\dev\repositories\BettIlias\Frontend\vite.config.ts
- C:\dev\repositories\BettIlias\Frontend\node_modules\.pnpm\[email protected]\node_modules\vite\dist\node\chunks\dep-0b3d3f5e.js
- C:\dev\repositories\BettIlias\Frontend\node_modules\.pnpm\[email protected]\node_modules\vite\dist\node\cli.js
- C:\dev\repositories\BettIlias\Frontend\node_modules\.pnpm\[email protected]\node_modules\vite\bin\vite.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:966:15)
    at Function.Module._load (internal/modules/cjs/loader.js:842:27)
    at Module.require (internal/modules/cjs/loader.js:1026:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.<anonymous> (C:\dev\repositories\BettIlias\Frontend\node_modules\.pnpm\[email protected]_@[email protected]\node_modules\vite-plugin-icons\dist\index.js:74:13)
    at Module._compile (internal/modules/cjs/loader.js:1138:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
    at Module.load (internal/modules/cjs/loader.js:986:32)
    at Function.Module._load (internal/modules/cjs/loader.js:879:14)
    at Module.require (internal/modules/cjs/loader.js:1026:19)
 ERROR  Command failed with exit code 1.

Default class isn't merged

Using Vue 2 compiler, setting a class on the icon component overrides the default class:

/** @type {import('unplugin-icons').Options} */
const unpluginIconsOptions = {
  compiler: 'vue2',
  defaultClass: 'base-icon svg-wrap',
}
<template>
  <IconCustomSend class="no-info"/>
</template>

Result:

<svg data-v-ad45f71a="" class="no-info">...</svg>

Vite + React build fails

Screen Shot 2021-09-16 at 10 56 45

Screen Shot 2021-09-16 at 10 57 15

vite.config.ts

import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
import tsconfigPaths from 'vite-tsconfig-paths'
import Icons from 'unplugin-icons/vite'
import { visualizer } from 'rollup-plugin-visualizer'

export default defineConfig({
  plugins: [
    reactRefresh(),
    tsconfigPaths(),
    Icons({ compiler: 'jsx', jsx: 'react' }),
    visualizer()
  ]
})

tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src",
    "target": "ESNext",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": false,
    "skipLibCheck": false,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react",
    "types": ["unplugin-icons/types/react"]
  },
  "include": ["./src"]
}

Dynamic icon components

Is it possible to dynamically use icons?

I'm using the vitesse template and would previously use something like <Icon :icon="myIconVariable" /> but now it seems like that no longer exists so I was wondering if it is still possible to do something like that.

I tried something like this without much luck

<template>
  <component :is="myIconVariable.replace(':', '-')" />
</template>

<script setup>
const myIconVariable = 'mdi:vuejs'
</script>

TS issue - Ambient module declaration cannot specify relative module name

Things are ok during development but I'm running into this issue when running vue-tsc --noEmit (as part of my build script).

I'm getting this issue:

node_modules/vite-plugin-icons/client.d.ts:9:16 - error TS2436: Ambient module declaration cannot specify relative module name.

9 declare module '/@vite-icons/*' {

It appears the TS compiler does not like declaring a module name starting with a "/"

Any ideas what's going on?

My tsconfig file:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "baseUrl": "./",
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "experimentalDecorators": true,
    "lib": ["esnext", "dom"],
    "types": ["vite/client", "node"],
    "paths": {
      "@/*": ["src/*"],
    }
  },
  "include": [
    "**/*.ts",
    "**/*.js",
    "src/**/*.tsx",
    "src/**/*.vue"
  ]
}

[vite-react] Runtime error in vite-react example

I'm trying to run the vite-react example from the examples folder, but am getting a runtime error. Here's what I did:

cd unplugin-icons
pnpm install
pnpm run build
cd examples/vite-react
pnpm run dev

The build completes, but when I open the browser I get this error in the console:

Uncaught ReferenceError: React is not defined
    at logosReact (react.jsx:2)
    at renderWithHooks (react-dom.development.js:14985)
    at mountIndeterminateComponent (react-dom.development.js:17811)
    at beginWork (react-dom.development.js:19049)
    at HTMLUnknownElement.callCallback2 (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at beginWork$1 (react-dom.development.js:23964)
    at performUnitOfWork (react-dom.development.js:22776)
    at workLoopSync (react-dom.development.js:22707)

The above error occurred in the <logosReact> component:

    at logosReact (http://localhost:3000/@id/~icons/logos/react.jsx:2:3)
    at header
    at div
    at App (http://localhost:3000/src/App.tsx:31:29)

Can't find icons after vite start with .vue ending

I tried to import my icons via the following two ways:

import IconStatusBlocked from '/@vite-icons/ph/hand.vue';

and

import IconStatusBlocked from 'virtual:vite-icons/ph/hand.vue';

To get TS support I added .vue to my imports which worked fine while the vite-server was running, but after a restart of vite I get this error:

 > html:/home/***.vue:3:30: error: Do not know how to load path: html:@vite-icons/ph/hand
    3 │ import IconStatusBlocked from 'virtual:vite-icons/ph/hand.vue';
      ╵                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 > html:/home/***.vue:8:30: error: Do not know how to load path: html:@vite-icons/ph/hourglass
    8 │ import IconStatusPending from 'virtual:vite-icons/ph/hourglass.vue';
      ╵                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

error when starting dev server:
Error: Build failed with 16 errors:
html:/home/***.vue:3:25: error: Do not know how to load path: html:@vite-icons/ic/sharp-timelapse
html:/home/***.vue:4:22: error: Do not know how to load path: html:@vite-icons/mdi/clock-time-eight-outline
html:/home/***.vue:5:23: error: Do not know how to load path: html:@vite-icons/mdi/source-branch
html:/home/***.vue:6:23: error: Do not know how to load path: html:@vite-icons/mdi/source-commit
html:/home/***.vue:3:30: error: Do not know how to load path: html:@vite-icons/ph/hand
...
    at failureErrorWithLog (/home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1449:15)
    at /home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1131:28
    at runOnEndCallbacks (/home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:921:63)
    at buildResponseToResult (/home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1129:7)
    at /home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1236:14
    at /home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:609:9
    at handleIncomingPacket (/home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:706:9)
    at Socket.readFromStdout (/home/***/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:576:7)
    at Socket.emit (events.js:315:20)
    at Socket.EventEmitter.emit (domain.js:467:12)
 ERROR  Command failed with exit code 1.

Autoload libraries with dashes fails

Hi!

I didn't find how to load icons like those:

mdi-light:alarm
noto-v1:flag-for-flag-japan

If I write:

<i-mdi-light-alarm></i-mdi-light-alarm>

it fails...

I took those names here. It works for libraries without dashes 🤔

Elusive Icons `el-` prefix conflicts with element-plus component `el-` prefix

In element-plus, components have the el- prefix (eg <el-button>Hi</el-button>

However, Elusive Icons also has an el- prefix.

Example:
<el-upload> = Element Plus component -> https://element-plus.org/#/en-US/component/upload
<el-upload> = Elusive icons icon -> https://iconify.design/icon-sets/el/upload.html

Elusive Icons always takes precedence in this case.

eg. <el-button> looks for the "button" icon in Elusive Icons. The intention with writing is rendering an Element Plus button but with vite-plugin-icons it's not possible, because the "el-" prefix is interpreted as an Elusive Icons prefix. The result is an error, because there's no el-button icon. el-upload is another case to consider, since el-upload is both a component and an icon.

Repro in Vitesse - install with npm install rather than pnpm (Link to branch and file with repro)

Icons break build after upgrading to a Vite versions greater than 2.0.0-beta.52

Problem:

If you update to any version of Vite greater than 2.0.0-beta.52 the following error will start appearing

Screen Shot 2021-01-31 at 10 41 59

This error comes from the components being generated by this plugin:

Screen Shot 2021-01-31 at 10 42 31

I'm not sure if this is a vite-plugin-icons issue or if something got broken is Vite in the latest releases. Given that only broken components are the icon ones I decided to post this issue here first. Thanks for the hard work on this amazing plugin!

Custom icons HMR

It doesn't seem that custom icons are being reloaded when changed. I need to fully restart vite for it to take changes into account. (Which can be quite tedious, as our app takes 15-20 secondes to load with vite.)

feat: generate svg sprite from used icons

just something that popped into my head a minute ago

  • collect all referenced icons into one svg sprite with ids for each (maybe one sprite per collection to avoid id clashes or prefixed-ids)
  • instead of the real icon svg return a wrapper that references the id with xlink:href

would save some for icons that are used repeatedly

Cannot find module '@iconify/json'

I have got the same error yesterday like #1 and tried to reproduce, but got another errors.

Here is the example repo.

git clone https://github.com/nandordudas/vite-plugin-icons
cd vite-plugin-icons
pnpm i # or yarn

After manually installed @iconify/json got another error.

Node: v15.5.1
OS: Manjaro Linux x86_64

[Feature Request] Icon collection alias

有一些图标集的名字很长例如 icon-park

如果prefix定义为 icon 时,使用起来很难受

<icon-icon-park-user />

是否可以支持图标集别名或重命名?

Vue 3 CLI and Auto Importing

Hello!

How to setup vue.config.js in order to support Auto Importing feature? I can't use "import from..." there, so can't do it like this (taken from the https://github.com/antfu/unplugin-icons#auto-importing):

import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'

Seems like I need to use "require", but how can I specify resolver for the unplugin-vue-components plugin?

Thanks!

Typings for imported icons

Hi! Any way to have typings for imported icons?

import IconHome from '/@vite-icons/oi/home'

has the usual no typings found error.
Have to import them rather than auto-import because they're being used in a list like this:

  { title: 'Home', icon: IconHome, link: '/' },

Trying to build a list of menu items like so

const items = reactive([
  // @ts-ignore
  { title: 'Home', icon: IconHome, link: '/' },
  { title: 'Counter', icon: IconCounter, link: '/Counter' },
  { title: 'Fetch data', icon: 'oi-list-rich', link: '/Fetch-Data' }
])

The string icons don't get imported as a component, and I can't figure out how to inline import them so I"m trying to just do the standard import but I get typing errors. Open to ideas.

icon size and alignment

If using Iconify directly, as described in https://docs.iconify.design/implementations/vue/, the size of icons is smaller and matches that of the text.

With vite-plugin-icons:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1.2em" height="1.2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M29.55 26.11l-3.05 1.52L23.66 21H15a2 2 0 0 1-2-2v-6a2 2 0 0 1 4 0v4h7v-2h-5v-2a4 4 0 0 0-8 0v1a9 9 0 1 0 8.77 11h-2.06A7 7 0 1 1 11 16v3a4 4 0 0 0 4 4h7.34l3.16 7.37l4.95-2.48z" fill="currentColor"></path><path d="M15.5 8A3.5 3.5 0 1 1 19 4.5A3.5 3.5 0 0 1 15.5 8zm0-5A1.5 1.5 0 1 0 17 4.5A1.5 1.5 0 0 0 15.5 3z" fill="currentColor"></path></svg>

With @iconify/vue@next:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M29.55 26.11l-3.05 1.52L23.66 21H15a2 2 0 0 1-2-2v-6a2 2 0 0 1 4 0v4h7v-2h-5v-2a4 4 0 0 0-8 0v1a9 9 0 1 0 8.77 11h-2.06A7 7 0 1 1 11 16v3a4 4 0 0 0 4 4h7.34l3.16 7.37l4.95-2.48z" fill="currentColor"></path><path d="M15.5 8A3.5 3.5 0 1 1 19 4.5A3.5 3.5 0 0 1 15.5 8zm0-5A1.5 1.5 0 1 0 17 4.5A1.5 1.5 0 0 0 15.5 3z" fill="currentColor"></path></svg>

Moreover, @iconify/vue@next has an InlineIcon component, which fits better for inline icons/texts. Is there any effortless way here to achieve the same effect?

Support a default collection for auto-import

Hi,

I was looking for something like a defaultCollection option for the IconsResolver but that doesn’t seem to exist yet. I usually try to stick to one icon collection in any single project, simply because the general art style is consistent and only use icons from other collections as kind-of last resort (though unplugin-icons definitively makes this much easier, thank you!).

Right now I’ve been using the system-uicons and it gets a little tedious to write <icon-system-uicons-plus/> when it probably could be <icon-plus/> instead and only if I want to deviate from my default I’d have to write something like <icon-mdi-account/>.

I thought I could get away with

IconsResolver({
  prefix: 'icon',
    alias: {
      '': 'system-uicons',
    }
})

but… curse this sudden but inevitable betrayal :).

Thank you for time & work,

Konrad

versions used:
[email protected]
[email protected]

dynamic use icon

how to use

  <icon-accessibility/>
  <icon-account-box style="font-size: 2em; color: red"/>

switch to

  <icon name="accessibility"/>
  <icon  name="account-box " style="font-size: 2em; color: red"/>

thus , I can dynamic use icon

  <icon :name="iconName"/>

as some time we need to show a batch of icon by some kind of logic,but now seem to not support, Maybe I miss something.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.