Example React Icons Component
September 28, 2021
You can’t escape using icons these days. They’re everywhere. And there is an almost endless amount of options when it comes to selecting which icon pack to use. Font Awesome is one of the more populate choices, but Material Icons are also a great choice.
Personally, I like creating svg React icons. Not creating them from scratch, but using existing, well designed icons from the web. My favorite choice for svg icons right now is heroicons. They’re clean and simple icons that are easy to use. Their site is also well designed, which shouldn’t come as a surprise since it’s done by the folks at Tailwindcss.
// package.json
...
"react": "^17.0.2",
...
// icons.jsx
import React from 'react';
import * as styles from './styles.module.css';
export const FireSvg = ({ modifier }) => (
<svg xmlns="http://www.w3.org/2000/svg" className={`${styles.icon} ${modifier}`} viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M12.395 2.553a1 1 0 00-1.45-.385c-.345.23-.614.558-.822.88-.214.33-.403.713-.57 1.116-.334.804-.614 1.768-.84 2.734a31.365 31.365 0 00-.613 3.58 2.64 2.64 0 01-.945-1.067c-.328-.68-.398-1.534-.398-2.654A1 1 0 005.05 6.05 6.981 6.981 0 003 11a7 7 0 1011.95-4.95c-.592-.591-.98-.985-1.348-1.467-.363-.476-.724-1.063-1.207-2.03zM12.12 15.12A3 3 0 017 13s.879.5 2.5.5c0-1 .5-4 1.25-4.5.5 1 .786 1.293 1.371 1.879A2.99 2.99 0 0113 13a2.99 2.99 0 01-.879 2.121z" clipRule="evenodd" />
</svg>
);
export const BadgeCheckSvg = ({ modifier }) => (
<svg xmlns="http://www.w3.org/2000/svg" className={`${styles.icon} ${modifier}`} viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
);
export const LightningBoltSvg = ({ modifier }) => (
<svg xmlns="http://www.w3.org/2000/svg" className={`${styles.icon} ${modifier}`} viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clipRule="evenodd" />
</svg>
);
/* styles.module.css */
/* Default icon styles */
.icon {
width: 38px;
height: 38px;
}
<div>
<FireSvg />
<BadgeCheckSvg />
<LightningBoltSvg />
</div>
So, here I’m taking the element from heroicons and dropping it into a react component. I give it a base style selector called icon
and I allow a modifier string to be passed to the className
attribute that changes the default styling as needed. This makes the react icons extremely flexible and resuable.
If I wanted the FireSvg
to be slightly smaller and red, I’d just need to create a new css selector in my styles.module.css
and pass the name of the selector to the FireSvg
component.
Another thing worth mentioning is that when working with svg
element in React, it’s important to remember to convert dash deliminated attributes to camelcame. A warning will show up in the console if this isn’t done.
For example: fill-rule
should be changed to fillRule
and clip-rule
should be changed to clipRule
.
/* styles.module.css */
...
.icon__red {
width: 24px;
height: 24px;
color: red;
}
<div>
<FireSvg modifier="icon__red"/>
</div>
The main drawback with this approach is that the modifier
selector is tightly coupled to the styles.module.css
file imported in icons.jsx
. For most projects this is fine, but on larger projects where icons are used in many different places it might become an issue. Overall, I think this a great approach for creating react icons.