5 min read0 views

Why you (probably) don't need an icon library

Believe it or not, you don't need extra dependencies to add icons in your App as actual components. Be it Svelte, React, or SolidJS.

This is the BEST way to add icons.

I'll share with you my best-practice for adding icons in your App. I currently use these three frameworks: React, SolidJS, and Svelte, so I'll show you how to add and manage your icons in each of those projects, without compromising on flexibility..

You only need two things:

First, find an icon.

Go to Icones.js.org and search for the icon you want to add. Then click on the SVG button under "Snippets". For instance, I'll use this Marker Duotone icon. (The svg would be copied to your clipboard)

first step

Second, add it to your JS app.

Now that you've copied the SVG to your clipboard, you can add it to your app. I'll show you how to do it in React, SolidJS, and Svelte. I usually store my icons in this structure:

- src
  - assets
    - icons
      - index.ts
      - marker-duotone.tsx # This is your icon.
      - *.tsx # All your other icons.

You really only need to add {...props} and add the SVG attributes to the props types.

React

Create a new .tsx for your icon and extend the props with SVGProps<SVGSVGElement>:

// src/assets/icons/marker-duotone.tsx
import { SVGProps } from 'react';
 
export default function MarkerDuotone(props: SVGProps<SVGSVGElement>) {
    return (
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
            {/* Your SVG code here */}
        </svg>
    )
}

Prefix the named export with Icon it's easy to find with intellisense:

// src/assets/index.ts
export { default as IconMarkerDuotone } from './icons/marker-duotone';
// ... Do the same for the other icons here
 

Svelte 5

Create a new .svelte for your icon and extend the props with SVGAttributes<SVGSVGElement>:

<!-- src/assets/icons/marker-duotone.svelte -->
 
<script lang="ts">
  import type { SVGAttributes } from 'svelte/elements';
 
  let { ...restProps }: SVGAttributes<SVGSVGElement> = $props();
</script>
 
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...restProps}
  >
    <!-- Your SVG code here -->
  </svg
>

Prefix the named export with Icon it's easy to find with intellisense:

// src/assets/index.ts
export { default as IconMarkerDuotone } from './icons/marker-duotone.svelte';
// ... Do the same for the other icons here

SolidJS

Create a new .tsx for your icon and extend the props with JSX.SvgSVGAttributes<SVGSVGElement>:

// src/assets/icons/marker-duotone.tsx
import { JSX, mergeProps, VoidProps } from 'solid-js';
 
export default function MarkerDuotone(props: JSX.SvgSVGAttributes<SVGSVGElement>) {
    return (
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
            {/* Your SVG code here */}
        </svg>
    )
}

Prefix the named export with Icon it's easy to find with intellisense:

// src/assets/index.ts
export { default as IconMarkerDuotone } from './icons/marker-duotone';
// ... Do the same for the other icons here
 

Using your Icons

🥳 Congrats, you've added your icons! It's as easy as doing this now:

// You can even customize the size of your icon or add classes to it.
<IconMarkerDuotone width="35" height="35" className="text-blue-500 />

BONUS: Just save them as .svg files.

There's a much easier way by taking advantage of Vite Plugins. Unfortunately, this only works for React (vite-plugin-svgr) and SolidJS (vite-plugin-solid-svg). But this way, you can store your icons like so:

- src
  - assets
    - icons
      - index.ts
      - marker-duotone.svg
      - *.svg # All your other icons.

Use .svg-only with SolidJS

  1. Install vite-plugin-solid-svg.
  2. Add it to your vite.config.ts file.
// vite.config.ts
import { defineConfig } from 'vite';
import solidSvg from 'vite-plugin-solid-svg';
 
export default defineConfig({
  plugins: [solidSvg()],
});
  1. Usually, .svg imports are 'string' types, not JSX. To fix this, add this to tsconfig.json:
// tsconfig.json
{
  "compilerOptions": {
    // ...
    "types": [
      "vite-plugin-solid-svg/types-component-solid", // Make sure this is above "vite/client"
      "vite/client", // Replaces `/// <reference types="vite/client" />` in vite-env.d.ts. Make sure that is removed.
    ],
  },
}
  1. In your assets/index.ts file, you can import the .svg this way:
// src/assets/index.ts
import { default as IconMarkerDuotone } from './icons/marker-duotone.svg';

Use .svg-only with React

  1. Install vite-plugin-svgr.
  2. Add it to your vite.config.ts file.
// vite.config.ts
import { defineConfig } from 'vite';
import svgr from 'vite-plugin-svgr';
 
export default defineConfig({
  plugins: [svgr()],
});
  1. Usually, .svg imports are 'string' types, not JSX. To fix this, add this to tsconfig.json:
// tsconfig.json
{
  "compilerOptions": {
    // ...
    "types": [
      "vite-plugin-svgr/client", // Make sure this is above "vite/client"
      "vite/client", // Replaces `/// <reference types="vite/client" />` in vite-env.d.ts. Make sure that is removed.
    ],
  },
}
  1. In your assets/index.ts file, you can import the .svg this way:
// src/assets/index.ts
import { default as IconMarkerDuotone } from './icons/marker-duotone.svg?react';


You've reached the end!**** Thanks for reading! 🥳