Building Custom SVG Icons with Color Replacement in Next.js
Published: 2023-06-25 13:17:28

In this tutorial, we will explore how to create a custom SVG icon component in Next.js that allows us to dynamically replace the fill color of the SVG using a provided color value. We will leverage the Next.js framework, React, and basic SVG manipulation techniques to achieve this functionality.

#### Prerequisites

Before we begin, make sure you have the following prerequisites:

- Basic understanding of Next.js, React, and JavaScript.
- Familiarity with SVG syntax and concepts.

#### Step 1: Setting up the Project

1. Create a new Next.js project by running the following command:

   ```
   npx create-next-app icon-color-replacement
   ```

2. Navigate into the project directory:

   ```
   cd icon-color-replacement
   ```

3. Install and enable the `svg-inline-loader` package, which will help us load and manipulate SVGs:

   ```
   npm install svg-inline-loader --save-dev
   ```

4. Update `next.config.js` to have the following webpack config changes:

   ```javascript
   const nextConfig = {
       webpack: (config) => {
           config.module.rules.push({
               test: /\.svg$/,
               loader: 'svg-inline-loader'
           });
           return config;
       }
   }

   module.exports = nextConfig;
   ```

5. Create a new file named `icons.type.ts` inside the `./components` directory and define the `IconsType` type to hold the available icon names.

6. Similarly, create another file named `colors.type.ts` inside the `./styles` directory and define the `ColorsType` type to hold the available color values.

#### Step 2: Building the Icon Component

1. Create a new file named `Icon.tsx` inside the `./components` directory.

2. Import the required dependencies:

   ```jsx
   import React, { useEffect, useRef } from 'react';
   import { IconsType } from './icons.type';
   import { ColorsType } from '@/styles/colors.type';
   ```

3. Define the `IconProps` interface which extends `React.SVGAttributes<HTMLOrSVGElement>` and includes additional properties like `name`, `width`, `height`, and an optional `color`:

   ```jsx
   interface IconProps extends React.SVGAttributes<HTMLOrSVGElement> {
       name: IconsType;
       width: number;
       height: number;
       color?: ColorsType;
   }
   ```

4. Create the `replaceColor` function that takes the SVG string and the new color as arguments. This function replaces the `fill` attribute with the provided color value using regex:

   ```jsx
   const replaceColor = (svgString: string, newColor: string) => {
       const regex = /fill="#[A-Fa-f0-9]{6}"/g;
       const replacement = `fill="var(${newColor})"`;
       return svgString.replace(regex, replacement);
   };
   ```

5. Export the `Icon` functional component. Inside the component, define a `useRef` hook to access the SVG element, and a `useEffect` hook to fetch the SVG and handle the color replacement logic:

   ```jsx
   export const Icon: React.FC<IconProps> = ({ name, width, height, color = '--c-oxford-blue-500', ...props }) => {
       const svgRef = useRef<SVGSVGElement>(null);

       useEffect(() => {
           const svgElement = async () => await import(`../../../public/icons/${name}.svg`);

           svgElement().catch(e => {
               console.error('<strong

>On loading the SVG</strong>', e);
           });

           svgElement().then(svg => {
               svgRef!.current!.innerHTML = replaceColor(svg.default, color);
           });

       }, [name, color]);

       return <svg width={width} height={height} ref={svgRef} {...props}></svg>;
   };
   ```

#### Step 3: Using the Icon Component

1. Open the `pages/index.tsx` file.

2. Import the `Icon` component:

   ```jsx
   import { Icon } from '@/components/Icon';
   ```

3. Use the `Icon` component in your JSX code, providing the required props like `name`, `width`, and `height`, as well as an optional `color` prop:

   ```jsx
   const HomePage: React.FC = () => {
       return (
           <div>
               <h1>Icon Color Replacement Example</h1>
               <Icon name="example-icon" width={24} height={24} color="--c-crimson-red-500" />
           </div>
       );
   };
   ```

Congratulations! You have successfully created a custom SVG icon component in Next.js that allows you to replace the fill color dynamically. You can now customize the color of your SVG icons by passing different color values to the `color` prop of the `Icon` component.

Remember to import the necessary dependencies and define the required types before using the code in your Next.js project.

That's it! Have fun exploring and customizing your SVG icons with ease!