unplugin / unplugin-icons

🤹 Access thousands of icons as components on-demand universally.
https://www.npmjs.com/package/unplugin-icons
MIT License
3.65k stars 130 forks source link

Icons auto-import for Nuxt 3 #219

Closed ennioVisco closed 1 year ago

ennioVisco commented 2 years ago

Inspired by https://github.com/antfu/unplugin-icons/issues/213, it would be nice if there was a way to perform icons auto-import in nuxt 3.

However, the Nuxt 3 docs doesn't say how to implement it: https://v3.nuxtjs.org/guide/concepts/auto-imports#directory-based-auto-imports.

antfu commented 2 years ago

There is currently no way to do that in Nuxt, pending PRs for Nuxt 2:

While we haven't discussed about how we should implement it in Nuxt 3. Ideally, it would be better for Nuxt to expose a resolve function to match with unknown components similar to unplugin-vue-components. /cc @pi0

While on the other hand, I personally think UnoCSS's icon solution is generally better than this plugin (which works with both Nuxt 2 and 3 from day one) and I have moved most of my projects using it.

HayateLaTech commented 1 year ago

While I appreciate the blog-post about UnoCSS and it being a solution that actually works, I think I'll write a quick tutorial how to make it all work in Nuxt 3 directly.

Like seriously xD I've been trying for 3 days straight to make unplugin-icons work in Nuxt 3 and this has been giving me so many headaches.. ;w; and finding the solution the one and only antfu also switched for is hella difficult xD That basically the same outcome can be achieved so easily blows my mind x3

npm npm i -D @unocss/nuxt @unocss/preset-icons @iconify/json

nuxt.config.ts

modules: [
    '@unocss/nuxt',
],
unocss: {
    // presets
    uno: false, // enabled "@unocss/preset-uno"
    icons: true, // enabled "@unocss/preset-icons"
    attributify: false, // enabled "@unocss/preset-attributify"

    // core options
    shortcuts: [],
    rules: [],
},

components/somefolder/something.vue

<template>
  <div>
    <div class="i-vscode-icons:file-type-json"></div>
  </div>
</template>

Useful Tools

And don't get me wrong, I really appreciate all the things you create - you make webdev so much more great.. but unplugin-icons and nuxt 3 and all the posts with half-assed vite solutions really drive me mad xD so I hope this post here can help ease some peoples minds too, finally ^w^

ennioVisco commented 1 year ago

Thanks for the guide, I'm sure it will be useful to many. I'm still puzzled about the div-based approach to be honest: I like the component-oriented approach, I think it looks cleaner and more intuitive, although I do recognize the benefits that @antfu cleverly points out in his article.

Moreover, while I can recognize the benefits of UnoCSS in an Atomic-CSS settings, I see little to no value when not using Atomic CSS, unfortunately.

I prefer a different "composable" approach, based on SASS mixins, like in the example shown here:

<template>
    <button :class="$style['btn--dark']">Sample button</button>
</template>

<style module lang="scss">
@use  "@/assets/css/settings";

.btn--dark {
    background-color: settings.background;
}
</style>

This is much more meaningful and relies on an almost-standard CSS syntax (instead of having to learn the atomic CSS unreadable meta-language that basically reproduces CSS)

antfu commented 1 year ago

Thanks for the detailed guide @HayateLaTech!

Unfortunately I think in the short run unplugin-icons won't be able to auto-import in Nuxt due to lack of some APIs required.

If you still prefer to use dev based approach you may also try with https://twitter.com/Atinux/status/1566908478286958593.

husayt commented 1 year ago

I found unocss to be the most organic/holistic way to get icons working in line with tailwind syntax/dynamic icons/icon classes and etc. With that you don't need any other libraries including this one.

You can have multiple styles for icons and most importantly this works in framework agnostic way i.e. across vue, react, svelte and etc

<div class="i-heroicons-solid:academic-cap" />
<div i-heroicons-solid:academic-cap />
<unoIcon i-heroicons-solid:academic-cap />

One tip: to get dynamic icons working just add them to safelist in unocss.config

Idered commented 1 year ago

This works for me in nuxt 3:

import { defineNuxtConfig } from 'nuxt'
import IconsResolver from 'unplugin-icons/resolver'
import Icons from 'unplugin-icons/vite'
import Components from 'unplugin-vue-components/vite'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig(async () => ({
  modules: [
    ['unplugin-icons/nuxt']
  ],
  vue: {
    template: {
      compilerOptions: {
        isCustomElement: (tag) => tag.startsWith('i-'),
      },
    },
  },
  vite: {
    plugins: [
      Components({
        resolvers: [IconsResolver()],
      }),
      Icons({}),
    ],
  },
}))
ennioVisco commented 1 year ago

This works for me in nuxt 3:

import { defineNuxtConfig } from 'nuxt'
import IconsResolver from 'unplugin-icons/resolver'
import Icons from 'unplugin-icons/vite'
import Components from 'unplugin-vue-components/vite'

// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig(async () => ({
  modules: [
    ['unplugin-icons/nuxt']
  ],
  vue: {
    template: {
      compilerOptions: {
        isCustomElement: (tag) => tag.startsWith('i-'),
      },
    },
  },
  vite: {
    plugins: [
      Components({
        resolvers: [IconsResolver()],
      }),
      Icons({}),
    ],
  },
}))

Closing: either adopt the quoted message, or the official nuxt-icon module, or UnoCSS icons preset.