antfu / unplugin-icons

🤹 Access thousands of icons as components on-demand universally.

Home Page:https://www.npmjs.com/package/unplugin-icons

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Trouble with importing icons in a vite/react project

Skia69 opened this issue · comments

Hello, i tried to follow the documentation as best as i could in order to use unplugin-icons in a react/vite project and it looks like i wasn't really successful

My vite.config is as follows:

import react from '@vitejs/plugin-react'
import * as path from 'path'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import Icons from 'unplugin-icons/vite'
import { defineConfig } from 'vite'
import eslintPlugin from 'vite-plugin-eslint'

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        react(),
        eslintPlugin(),
        Icons({
            compiler: 'jsx',
            jsx: 'react',
            customCollections: {
                'my-icons': FileSystemIconLoader('./src/assets/icons', (svg) =>
                    svg.replace(/^<svg /, '<svg fill="currentColor" ')
                ),
            },
        }),
    ],
    resolve: {
        alias: {
            '@': path.resolve(__dirname, './src'),
        },
    },
})

As you can see, my svg icons are located inside src/assets/icons

Now, here's how i'm trying to import the icons in one of my components:

import IconHome from '~icons/my-icons/home'

But it's throwing the following error:
[vite] Internal server error: No files matching '~icons/my-icons/home.jsx' were found.

Any help would be appreciated!

@Skia69 your collections must go inside customCollections option: https://github.com/antfu/unplugin-icons#custom-icons

EDIT: uhhm you update the code snippet.

@Skia69 your collections must go inside customCollections option: https://github.com/antfu/unplugin-icons#custom-icons

EDIT: uhhm you update the code snippet.

Yup, sorry for the confusion. It still doesn't work and i have no idea how to fix it

@Skia69 have you installed @svgr/core dev dependency? it is required, check React entry here https://github.com/antfu/unplugin-icons#frameworks

You should use also @vitejs/plugin-react-refresh instead @vitejs/plugin-react but I'm not an expert on react, check the examples/vite-react example (no custom icons).

@Skia69 have you installed @svgr/core dev dependency? it is required, check React entry here https://github.com/antfu/unplugin-icons#frameworks

You should use also @vitejs/plugin-react-refresh instead @vitejs/plugin-react but I'm not an expert on react, check the examples/vite-react example (no custom icons).

Yes mate, i followed the steps in the link you just shared and i installed the necessary dependencies but it still didn't work

@Skia69 can you share a minimal repro github or stackblizt? I'll check the vite-react example...

@Skia69 can you share a minimal repro github or stackblizt? I'll check the vite-react example...

Sure, i'll do it tomorrow once i wake up. I'm away from my pc right now

@Skia69 you've a working repo with custom icons and logos collection here: https://stackblitz.com/edit/vitejs-vite-dinjys

@Skia69 you've a working repo with custom icons and logos collection here: https://stackblitz.com/edit/vitejs-vite-dinjys

Thank you bro, i managed to get it sorted out thanks to you. The main issue was that the vite-plugin-eslint plugin is breaking my application every time i import an svg using this syntax import IconHome from '~icons/app-icons/home'

I didn't know how to solve it, so i ended up disabling the eslint plugin altogether

@Skia69 can you share you eslint configuration?

@Skia69 can you share you eslint configuration?

Here it is:

   {
    "root": true,
    "parserOptions": {
        "ecmaVersion": 2020,
        "sourceType": "module",
        "ecmaFeatures": {
            "jsx": true
        }
    },
    "settings": {
        "react": {
            "version": "detect"
        },
        "import/resolver": {
            "node": {
                "paths": ["src"],
                "extensions": [".js", ".jsx", ".ts", ".tsx"]
            }
        }
    },
    "env": {
        "browser": true,
        "amd": true,
        "node": true
    },
    "extends": [
        "eslint:recommended",
        "react-app",
        "plugin:react/recommended",
        "plugin:react-hooks/recommended",
        "plugin:jsx-a11y/recommended",
        "plugin:prettier/recommended"
    ],
    "plugins": ["simple-import-sort", "prettier"],
    "rules": {
        "prettier/prettier": [
            "error",
            { "endOfLine": "auto" },
            {
                "usePrettierrc": true
            }
        ],
        "react/react-in-jsx-scope": "off",
        "jsx-a11y/accessible-emoji": "off",
        "react/prop-types": "off",
        "simple-import-sort/imports": "warn",
        "simple-import-sort/exports": "warn",
        "jsx-a11y/anchor-is-valid": [
            "error",
            {
                "components": ["Link"],
                "specialLink": ["hrefLeft", "hrefRight"],
                "aspects": ["invalidHref", "preferButton"]
            }
        ]
    }
}

One more question, please
I'm trying to make it so that i can change the svg color dynamically by using this code snippet:

 plugins: [
        react(),
        Icons({
            compiler: 'jsx',
            jsx: 'react',
            customCollections: {
                'app-icons': FileSystemIconLoader('./src/assets/app-icons', (svg) => {
                    svg.replace(/^<svg /, '<svg fill="currentColor" ')
                    console.log(svg)
                    return svg
                }),
            },
            iconCustomizer(collection, icon, props) {
                console.log(`Collection: ${collection} => Icon: ${icon}`)
            },
        }),
        // eslintPlugin(),
    ],

The fill="currentColor" is not being inserted into my svg component. Any clue why?

@Skia69 you should configure it on the container or in the component, I mean the color, text-red-500 for example if using UnoCSS or using a style/class on it: class="text-red-500" or style="color: red"

@Skia69 you should configure it on the container or in the component, I mean the color, text-red-500 for example if using UnoCSS or using a style/class on it: class="text-red-500" or style="color: red"

It's not really working,
This is what it looks like in my console
Screenshot 2022-05-07 205532
As you can see, the fill="currentColor" property is nowhere to be found

try just removing the fill attr

try just removing the fill attr

Actually, if you play attention closely, you can notice that the svg already these properties width="24" height="24" viewBox="0 0 24 24" fill="none"
Do you know how i can remove and replace them with my own attributes?

I mean, you must remove the fill attr from the svg, the plugin (via @iconify/utils) will not check for duplicates attrs IIRC.

just remove them from the svg, add the iconCustomizer(collection, icon, props) to the plugin and add the new attrs to the props, check for the collection and the icon if you need some custom props, it is a Record<string, string>.

For example, check this, only iconCustomizer: unocss/unocss#848 (comment)

you can also change the attrs on the svg it is on your local file system

Updated my repro, check the apple icons on the screen, one white and the same with red color using:

<Apple />
<Apple style={{ color: '#FF0000' }} />

EDIT: on iconCustomizer(collection, icon, props) you can see I only add the fill attr to this icon in my-icons collection

you can also change the attrs on the svg it is on your local file system

Yes, i had to swap fill attr with fill="currentColor" manually since almost all my svg's have more than one path with a hardcoded fill and i didn't really know how to configure it through vite 🤣 🤣

For example, the following svg has 2 paths which each has a hardcoded fill attr

<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 18.75C11.59 18.75 11.25 18.41 11.25 18V15C11.25 14.59 11.59 14.25 12 14.25C12.41 14.25 12.75 14.59 12.75 15
V18C12.75 18.41 12.41 18.75 12 18.75Z" fill="#292D32"/>
<path d="M17.6009 22.5601H6.40094C4.58094 22.5601 2.92094 21.1601 2.62094 19.3701L1.29094 11.4001C1.07094 10.1601 1.6809
4 8.57007 2.67094 7.78007L9.60094 2.23007C10.9409 1.15007 13.0509 1.16007 14.4009 2.24007L21.3309 7.78007C22.3109 8.5700
7 22.9109 10.1601 22.7109 11.4001L21.3809 19.3601C21.0809 21.1301 19.3809 22.5601 17.6009 22.5601ZM11.9909 2.93007C11.46
09 2.93007 10.9309 3.09007 10.5409 3.40007L3.61094 8.96007C3.05094 9.41007 2.65094 10.4501 2.77094 11.1601L4.10094 19.12
01C4.28094 20.1701 5.33094 21.0601 6.40094 21.0601H17.6009C18.6709 21.0601 19.7209 20.1701 19.9009 19.1101L21.2309 11.15
01C21.3409 10.4501 20.9409 9.39007 20.3909 8.95007L13.4609 3.41007C13.0609 3.09007 12.5209 2.93007 11.9909 2.93007Z" fil
l="#292D32"/>
</svg>

I removed em manually and now the color is applied dynamically

@Skia69 can you fork my repro and configure the eslint and the vite-eslint-plugin? I added your previous config and both deps, eslint and vite-eslint-plugin, but still with errors starting the dev server.

Yes, i had to swap fill attr with fill="currentColor" manually since almost all my svg's have more than one path with a hardcoded fill and i didn't really know how to configure it through vite 🤣 🤣

You can also check this https://github.com/antfu/unplugin-icons#advanced-custom-icon-set-cleanup, check the repo and the article from @iconify: you can optimize your custom icons without having to change them manually (IIRC)

@Skia69 can you fork my repro and configure the eslint and the vite-eslint-plugin? I added your previous config and both deps, eslint and vite-eslint-plugin, but still with errors starting the dev server.

Here's my repo with all the eslint configs/plugins included:
https://stackblitz.com/edit/vitejs-vite-zskibi?file=.eslintrc,package.json,src%2Fmain.tsx

If you disable the eslint vite plugin, the app will work normally and that's how i managed to get it to work

@Skia69 check this https://stackblitz.com/edit/vitejs-vite-wm9ode?file=.eslintrc, should work but I'm not an expert on eslint, check line 14: https://github.com/import-js/eslint-plugin-import/blob/main/README.md#importignore

Another solution will be exclude that rule: hannoeru/vite-plugin-pages#41 (comment) and next comment

I really app

@Skia69 check this https://stackblitz.com/edit/vitejs-vite-wm9ode?file=.eslintrc, should work but I'm not an expert on eslint, check line 14: https://github.com/import-js/eslint-plugin-import/blob/main/README.md#importignore

Another solution will be exclude that rule: hannoeru/vite-plugin-pages#41 (comment) and next comment

Thank you for taking the time to help me, i really appreciate it!
I'm not really fluent with all those eslint rules - the easiest fix for me was to disable the vite-eslint plugin altogether :/

Ok, so, can you close this issue?