Color Shades Generator in React

Color Shades Generator in React

In this hands-on project, we will generate different shades of the given color. we will be using the React.js framework

Introduction

This is the first of many projects that we are going to build in React. Before going into the details, first look at the demo of the project that we are building to have some idea. Color shades Generator and the source code is present in Github repo

Anyone who is in the field of web-dev understands the importance of shades of color. On any website, we will be using different shades of the same primary color for headings, and backgrounds.

What concepts we are going to use?

  • Forms
  • useState and useEffect hooks in React
  • Beautiful module which provides different shades of color - values.js

project in a nutshell

  1. User enters the hex value of color
  2. we pass the color to Values.js module to get different shades.
  3. Display the colors and add copy to clipboard feature.

Brushing up prerequisites

  • useState hook - useful for keep tracking the state of any variable. It provides the function to modify the state.
import React, { useState } from "react";
const [color, setColor] = useState('#23878a')

// Now state value of color is '#23878a'. If we want to modify it we can use setColor function that is returned by the hook

// to change the value 
setColor('#d3d3d3')
  • useEffect hook - This will be useful for doing side effects in the projects. Let's say we need to change the title of a webpage based on button click or go to the payment/subscriptions page or fetch the data from API and so on... In this project, we will be using this for only the initial load of color. So that when the application loads already some color shades are generated.
import React, { useEffect } from "react";
// in the below code, we are generating initial shades and changing the state of shades.
  useEffect(() => {
    const initial_color = "#23878a";
    const initial_shades = new Values(initial_color).all(10);
    setShades(initial_shades);
  }, [])

// note the second argument to hook which is the dependency list. We passed the empty array list. Essentially we are saying don't re-render if the state of any variable is changed after the initial load.

✔ Setting up the project

  • First and foremost check node is installed or not. If not you can download it from the official site node js website In this project, I am using the latest versions of node and npm. You can find yours by the following commands :
 E:\> npm --version
8.12.1
E:\> node --version
v18.4.0
  • For react setup, we will be using create-react-app, which will install all dependencies and set up skeleton for us.
npx create-react-app color-generator
cd  color-generator
npm start

We can also use cdn, but the above command will be straightforward. Once we run npm start, dev server will be started on the localhost 3000 port.

  • Removing all boilerplate codes

    We don't need all the boilerplate code created by create-react-app. We need to remove all the unnecessary files. After removing files, my working directory.

$ tree -L 2 
├── README.md
├── package-lock.json
├── package.json
├── public
│   └── index.html
└── src
    ├── App.css
    ├── App.js
    ├── index.css
    └── index.js
  • install values.js dependency
npm i values.js

That's it. All the required setup for the project is done. The first big step is done.

✔ Writing the Components

For modularity, it is good practice to create components directory inside the src and place the components inside it.

As we know, everything in React is components, we will be creating 2 components

  • AllColors.js -> Most of the heavy lifting is done here
  • Color.js -> single color component.

AllColors.js

  • Setting up of hooks :

    const [color, setColor] = useState("#23878a");
    const [shades, setShades] = useState([]);
    
    // We are initializing the shades with sample color. so when the page loads, shades are loaded.
    useEffect(() => {
      const initial_color = "#23878a";
      const initial_shades = new Values(initial_color).all(10);
      setShades(initial_shades);
    }, []);
    
  • On submit, we will set the new color based on the user input. That can be handled by the below code :

// most of the code is self-explanatory. we are taking the event object and preventing the refresh of page on submit.
  const handleSubmit = (e) => {
    e.preventDefault();
// if user enters wrong hex color, values.js module throws error. That is captured using try and catch block
    try {
      setShades(new Values(color).all(10));
    } catch (e) {}
  };
  • Once user submits, and shades are set, we will pass each shade to color component
      <div >
        {shades.map((shade, index) => {
          return <Color key={index} clr={shade} index={index} />;
        })}
      </div>

That's it. That's all in this component. Find the completed component code here : AllColors.js

Color.js

  • values.js function returns rgb value of each shade. we can display the same in each block. if we want to convert it into hex value, we can use the following util function
function componentToHex(c) {
  var hex = c.toString(16);
  return hex.length === 1 ? "0" + hex : hex;
}

function rgbToHex([r, g, b]) {
  return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
}

✔ Implementing copy to clipboard feature code :

User clicks on any block, the hex code is copied to the clipboard and we display an alert. we remove the alert in 2 seconds. For this, we will be using useEffect hook with setTimeout.

// initially, state is false. so it won't be visible.
const [showCopy, setShowCopy] = useState(false);

  // this is used to automatically hide the clipboard message in 2 seconds.
// this will run whenever there is a change in state of showCopy.
  useEffect(() => {
    setTimeout(() => {
      setShowCopy(false);
    }, 2000);
  }, [showCopy]);

so using onclick event on div, we change the state of showCopy to true. Once the state is changed, useEffect runs and closes the message by setting the state to false.

Remaining code of the component is :

    <div
      //   className="single-color"
      className={`single-color ${index > 10 && "color-light"} `}
      style={{ backgroundColor: hex }}
      onClick={() => {
        navigator.clipboard.writeText(hex);
        setShowCopy(!showCopy);
      }}
    >
      <p>{hex}</p>
      <p>{weight}%</p>
// we are using conditional rendering here. 
      <span >
        {showCopy ? "Copied to clipboard!" : ""}
      </span>
    </div>

The complete source code for the component is found here : Color.js

Now we have a functioning color shades generator. which will be ugly without styles. You can find the code for corresponding styles in the Github repo.

Conclusion

If you like the project and wish to extend it, we can also take user input for the required shades and generate instead of fixed 20 shades (light and dark) for a given color. This is as easy as adding a new element in the form and pass into values.js

This is a great beginner to intermediate level project where we use different concepts like hooks, conditional rendering, handling form events, and passing different props across components. Any feedback, suggestions, or mistakes is highly appreciated.

Thanks for reading. Until next time 👋👋👋