icons and dynamic SVGs

This note talks about the different ways you can import and use icons in a project.
And ways to dynamically change the color and size of them to avoid having multiple variations of the same SVG in your project.

using font file

fonts can have icons in the form of glyphs. can be considered one of the characters of the font
To use these icons install the font in your project and copy / paste the glyph.
You can change color of icon by changing font color.

font awesome

is a somewhat unique case which offers 2 methods to implement

importing all font awesome icons or an entire icon pack is ineficient, using https://icomoon.io/ you can select individual icons and download them.

using svg files

SVGs (scalable vector graphics) are XML based text file that describes 2D vector graphics
the colors are defined inside the svg with attributes like fill or stroke.
Importing and using an SVG image doesn't let you dynamically change it's attributes since it is a static file with hard coded values.

html/jsx

embed an SVG directly into your HTML or JSX
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" class="icon"> <path d="M..."></path> </svg>
You can use the currentColor value, which makes the SVG's color inherit the color property of its parent element. For example:
<div style="color: red;"> <svg ... fill="currentColor"></svg> </div>

This option isn't very practical

svg react component

manually transform your SVG file into a react component using tools like https://react-svgr.com/playground/, https://www.svgviewer.dev/svg-to-react-jsx or transform.tools and place them in your project.

Reminder that in Nextjs you can't serve react components in the /public dir and assets in this dir are not part of your apps final bundle.
You need to put the new component in a dir like /src/assets/images/, making it a part of your app bundle, making it larger.
This method is recommended for small SVGs you need to be dynamic.

svgr

The svgr package automates the process of transforming SVGs into react components when you import them. There are similar packages like 'svg-inline-loader' but svgr is the most popular one.

to import SVGs as components with svgr you'll need create a dir like /src/assets/images/ since in Nextjs the svgs in the /public dir are served statically so they aren't processed by Webpack.

Normally when you import an svg in Nextjs it calls the file-loader tool and you get a JS object with info about the file like src, width and height.
When you add the svgr configuration you tell Nextjs "Hey, when you see an import for an .svg file from a .js or .tsx file, don't use your default file-loader. Instead, use SVGR to transform the SVG's code into a full-fledged React component."

Steps to add SVGR to your project: https://react-svgr.com/docs/next/

Might need to manually modify your svgs to have fill="currentColor" instead of a hardcoded value
Example usage of imported svg components:

import MoreIcon from '@images/more-icon.svg';
...
<MoreIcon width={6} height={20} style={{ color: anchorEl ? iconColorActive : iconColorDefault }} />

The default config provided by svgr tries to import all svgs as components. This is a problem bc in my case my project already contains hundreds of cases where it imports SVGs the regular way and uses them like this:
<Image src={navProfileIcon.src} width={20} height={20} />

to fix this we have to extend the svgr config (in the next.config.ts file) even further with two options:

import attachIcon from '@images/attach-icon.svg?url'; // imports js obj
import attachIcon from '@images/attach-icon.svg?react'; // imports react component