vuetifyjs/nuxt-module

Add custom icon font

Closed this issue · 18 comments

I would like to add a Phosphor icons to my project, and I am trying to include it as a custom icon set like described in the Vuetify documentation. However it looks like this module doesn't accept custom icon sets:

interface IconsOptions {
    /**
     * @default 'mdi'
     */
    defaultSet: IconSetName;
    /**
     * The prefix for UnoCSS Preset Icons.
     *
     * @default 'i-'
     */
    unocssIconPrefix?: string;
    sets?: IconFontName | IconFontName[] | FontIconSet[];
    svg?: {
        mdi?: JSSVGIconSet;
        fa?: FontAwesomeSvgIconSet;
    };
}

If I look at the types from Vuetify I can see that sets should accept a component

interface IconSet {
    component: IconComponent;
}
type IconOptions = {
    defaultSet?: string;
    aliases?: Partial<IconAliases>;
    sets?: Record<string, IconSet>;
};

which corresponds well with the Vuetify docs for adding a custom icon sets using a render function.

@AasmundN can you provide a minimal repro (with plain Vuetify + Vite)? how do you consume the icons? I mean, Phosphor icons are fonts, JS (like mdijs), or can be consumed via SVG?

Have you tried using UnoCSS Preset Icons with Iconify Phosphor icon set?

https://icon-sets.iconify.design/ph/

I was thinking something along the line of this https://stackblitz.com/edit/vue3-vite-starter-fucq1w?file=src%2Fmain.js,src%2FApp.vue,src%2Fstyle.css. Can't get it to work though. Could also try to consume the icons with CSS like you suggested.

@AasmundN sorry, I was finishing some PR in another repos: here a working example via UnoCSS Preset Icons, the unocss-mdi icon set and using Phosphor icons in vuetify components:

https://stackblitz.com/edit/nuxt-starter-pabqmi?file=package.json,unocss.config.ts,nuxt.config.ts,vuetify.config.ts,app.vue

@AasmundN here an example with Phosphor and Vuetify https://stackblitz.com/edit/nuxt-starter-cgbvrr?file=phosphor%2Findex.ts,vuetify.config.ts

phosphor should provide this info, this issue is not related to this repo, you should solve the integration with Vuetify: check the phosphor/index.ts module, just a few aliases, you should map all Vuetify IconAlias (aliases) to the corresponding phosphor icon. You can also add multiple icon sets.

EDIT: your reproduction in SB is not working...

@AasmundN repo updated, plugin simplified:

import PhosphorIcons from '@phosphor-icons/vue';
import { aliases, phosphor } from '../phosphor';

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('vuetify:before-create', ({ vuetifyOptions }) => {
    vuetifyOptions.icons = {
      defaultSet: 'phosphor',
      aliases,
      sets: { phosphor },
    };
  });
  nuxtApp.hook('vuetify:ready', () => {
    nuxtApp.vueApp.use(PhosphorIcons);
  });
});

@userquin Is it possible to use any custom vue svg icon component and alias it to vuetify so it can use it as <v-icon>some icon</v-icon>? I can't see any option to do it in the config, so I assume it's also done by nuxt plugin and hooking into vuetify:before-create? Is there a simpler way to do this in the config.ts file?

@Q16solver unfortunately there is no support, it is complex to provide a solution that works with any icon provider, use custom and include the logic you need in the plugin hook

I guess that makes sense, the best way I've found is

import SomeIcon from "@/assets/icons/Icon.vue";
import { toKebabCase } from "@/util/text";

const ComponentMap: Record<string, Component> = {
  SomeIcon,
};

const IconComponentMap = Object.entries(ComponentMap).reduce<Record<string, Component>>(
  (acc, [name, component]) => {
    acc[toKebabCase(name).toLowerCase()] = component;
    return acc;
  },
  {},
);

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook("vuetify:before-create", ({ vuetifyOptions }) => {
    vuetifyOptions.icons = {
      sets: {
        custom: {
          component: (props) => h(props.tag, [h(IconComponentMap[props.icon as string], { class: "v-icon__svg" })]),
        },
      },
    };
  });
});

which lets me use <v-icon :icon="custom:some-icon" /> and be consistent enough

@userquin So I guess there's no way to expose the sets option for custom icon components in the config ts file. The other enquiry I had was regarding if it was possible for any really simple way to just only import SVGs because in the above example I have to make the svg a vue template for whatever reason and h(...) render the component which is a bit more boilerplate if I have a bunch of svg icons I have to transform to a vue file/component

@Q16solver have you tried unplugin-icons or NuxtIcon? I suggest you to use Unocss Preset Icons (svg icons to your css, if you only need the icon).

With unplugin-icons and UnoCSS Preset Icons you can use custom SVG files also from file system (no idea about Nuxt Icon): both using iconify icons (150000+ icons), check https://icones.js.org/ or https://icon-sets.iconify.design/

Check also https://vuetify-nuxt-module.netlify.app/guide/icons/unocss-preset-icons.html

@userquin Thanks for the example, I will check it out in a couple days. For now I just used @phosphor-icons/vue components in the Vuetify slots manually.

Here another example using Iconify Vue Icon: https://stackblitz.com/edit/nuxt-starter-akbfxa

@userquin thanks for the example provided. But icons don't work in UI components, for example in VRadio. Help me find a solution

The playground here has an example using custom icon for v-checkbox, maybe v-radio icons cannot be changed, check vuetify issues or ask in vuetify discord server.

Provide a small repro , maybe I can check it in a few hours.

The playground here has an example using custom icon for v-checkbox, maybe v-radio icons cannot be changed, check vuetify issues or ask in vuetify discord server.

Provide a small repro , maybe I can check it in a few hours.

I took your reproduction as a basis. https://stackblitz.com/edit/nuxt-starter-pdzvsr?file=app.vue,iconify%2Findex.ts
In the sources of the "VRadio" component, I saw that the "VIcon" component is used, an icon named "$radioOn" is passed in the parameters. I added this name to the aliases list, but it still doesn't work.

Even console.log does not return icon parameters that are declared inside ui components

@danilpon98 iconify-icon aliases are wrong, we should use dash instead colon (mdi- instead mdi:), I have changed some icons here:
https://stackblitz.com/edit/nuxt-starter-al4k5x

@danilpon98 iconify-icon aliases are wrong, we should use dash instead colon (mdi- instead mdi:), I have changed some icons here: https://stackblitz.com/edit/nuxt-starter-al4k5x

@userquin thanks))

New entry added to docs: https://vuetify-nuxt-module.netlify.app/guide/icons/integrations.html

If missing page await PWA update the new version.

Added NuxtIcon and unplugin-icons/nuxt entries and examples.