DEV Community

Cover image for Using Custom SVG Icons In React
Brandon Hills
Brandon Hills

Posted on

Using Custom SVG Icons In React

This is how I, a designer on a journey to more fully understand my design medium of choice, utilized my 2400 Icons in my Nextjs website.

I’m new at the modern webdev stuff. I understand HTML and CSS enough to get by, but my last round with object oriented programming was Visual Basic back in 2003 in my Freshman year of college. Today, I’m a designer who desires to ship his own products. So, of course, the first thing I wanted to do was use a custom icon set in my projects.

One of the first things I’ve picked up from my react mentors is to use props for everything. I wanted to figure out a way to represent an icon with a react component and call the icon by name with props.

Surprise, I couldn’t figure out a way to do that. However, I did find a way to change all of my .svg Icon files in to react components, which can work as easily as I want it to, perhaps even easier.

Changing the .svg to .jsx

Arrow Icons

Full Arrow Right.svg

<svg 
    width="24" 
    height="24" 
    viewBox="0 0 24 24" 
    fill="none" 
    xmlns="http://www.w3.org/2000/svg">
<path 
    d="M18.5 12H4" 
    stroke="#3E7BFA" 
    stroke-width="2" 
    stroke-linecap="round" 
    stroke-linejoin="round"
/>
<path 
    d="M13 6.5L18.5 12L13 17.5" 
    stroke="#555770" 
    stroke-width="2" 
    stroke-linecap="round" 
    stroke-linejoin="round"
/>
</svg>
Enter fullscreen mode Exit fullscreen mode

As you can see, I exported my icons from Figma with spaces in the name of the file. There are also hex values in place to determine the color of the icons, which we don’t want in case we decide to change the color.

SVGR

I used the SVGR command line interface tool to change my .svg to .jsx

SVGR Website Image

https://react-svgr.com/

From what I understand, this is included in create-react-app and Nextjs, so we can serve up any .svg file as a React component without having to install anything - but what we’re after is the easy functionality of calling the icon and changing the color dynamically.

I also found this nifty youtube tutorial created by user Mykhaylo Ryechkin who explains in depth how to create an icon component library.

Build an icon component library for React with SVGR and Rollup

SVGR Command Line Tool

If you’re using 2400 icons instead of just a couple, using the CLI was a no-brainer. Install and run the tool with:

npm install --save-dev @svgr/cli
# or use yarn
yarn add --dev @svgr/cli
Enter fullscreen mode Exit fullscreen mode

There’s a ton of options, and to fit my needs I had to play around with the SVGR Playground first, since I’m a visual learner, it helped me understand exactly what the CLI Inputs were doing and would turn my .svg in to.

I didn’t write a new script in my next.config.js file as I wasn’t creating a whole component library to host for anyone else to use, I just needed to transform the directory in to .jsx files. So, I ended up using

npx svgr --icon --title-prop --replace-attr-values "#3E7BFA=currentColor" --out-dir public/assets/ public/icons
Enter fullscreen mode Exit fullscreen mode

To break this down, the —icon option changed my width and height to 1em by default, which is great, because I’ve learned using Ems to determine the size of an icon will scale the icon up proportionally if the text size is increased.

The —title-prop option gives us a title prop and an aria-labelledby prop for accessibility options should we need it.

The —replace-attr-values replaces the hex value of ‘#3E7BFA’ with ‘currentColor’, which allows us to use a prop of color={theme.colors.primary} to set the color of the icon.

--out-dir public/icons/ public/assets lets us set the directory where our .svg files are located and set the directory of where we want our React components to go.

import * as React from "react";

const SvgFullArrowRight = ({ title, titleId, ...props }) => (
  <svg
    width="1em"
    height="1em"
    viewBox="0 0 24 24"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
    aria-labelledby={titleId}
    {...props}
  >
    {title ? <title id={titleId}>{title}</title> : null}
    <path
      d="M18.5 12H4"
      stroke="currentColor"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
    />
    <path
      d="m13 6.5 5.5 5.5-5.5 5.5"
      stroke="#555770"
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
    />
  </svg>
);

export default SvgFullArrowRight;
Enter fullscreen mode Exit fullscreen mode

After running the script, you’ll end up with a cloned directory, with all of your .svg files replaced with .jsx files and the spaces in the names of the files are removed. You’ll also notice an extra .jsx file in your directories called index.js.

// @create-index

export { default as FullArrowRight } from './FullArrowRight.js';
export { default as Add } from './Add.js';
export { default as AddAlarm } from './AddAlarm.js';
export { default as AddCall } from './AddCall.js';
export { default as AddCamera } from './AddCamera.js';
export { default as AddCart } from './AddCart.js';
Enter fullscreen mode Exit fullscreen mode

This is the file you’ll want to import in to any react components to use the icon library. You can import it like so:

import * as Icon from '../public/icons/Duotone/Index';
Enter fullscreen mode Exit fullscreen mode

This imports all of the exports from the icon index as a default object. You can access a specific icon by calling the icon import and using the name of the .jsx file together, for example, if I want the FullArrowRight icon to display as a react component:

<Icon.FullArrowRight />
Enter fullscreen mode Exit fullscreen mode

From here, we can set the props of width, height, and color like this: (remember, the default width and height is 1em)

<Icon.FullArrowRight 
    width='1.2em'
    height='1.2em'
    color={theme.colors.primar}
/>
Enter fullscreen mode Exit fullscreen mode

Now I feel like I'm starting to learn more and more about react. I've been on this journey for a couple weeks now, chipping away an hour or two at a time and learning by making lots of mistakes. You can find the front end of the project at https://makeros.branhills.com/ (A warning, most days this space will not look pretty)

The next step is to finish (refactor, probably) the navbar component by making it easier for me to change the information displayed on the menu and dropdowns.

If you have any tips or tricks I should try, @branhillsdesign on twitter. I'm always down to talk about best practices and learn from anyone ahead of me in the journey.

Top comments (0)