DEV Community

loading...
Cover image for React: How to create a custom progress bar component in 5 minutes

React: How to create a custom progress bar component in 5 minutes

ramonak profile image Katsiaryna (Kate) Lupachova Updated on ・3 min read

Originally posted on my personal blog

A couple of days ago, while working on one of React projects with the use of a very popular UI library, I’ve stumbled upon a problem: I needed to make some style changes of the Progress Bar component. But after struggling with it for a few hours and being in a complete desperation (why isn’t it working as it is written in the documentation???), I’ve decided to create a Progress Bar component from scratch. Here how I’ve made it.

1. Create a progress-bar.component.js file

import React from "react";

const ProgressBar = (props) => {
  const { bgcolor, completed } = props;
  return (
    <div>
      <div>
        <span>{`${completed}%`}</span>
      </div>
    </div>
  );
};

export default ProgressBar;
Enter fullscreen mode Exit fullscreen mode

Basically, the component consists of the two parts:

  1. the main parent div container - represents the whole bar
  2. the child div - completed part of the bar with the span which will show the completed percentage number.

Our custom progress bar component will receive just two props:

  • bgcolor - background color of the completed part of the bar
  • completed - number between 0 and 100

2. Add styling

Just for the sake of this tutorial, for styling, I’m going to use pure inline CSS. Another option would be to use the styled-components library, but let’s keep it simple.

const ProgressBar = (props) => {
  const { bgcolor, completed } = props;

  const containerStyles = {
    height: 20,
    width: '100%',
    backgroundColor: "#e0e0de",
    borderRadius: 50,
    margin: 50
  }

  const fillerStyles = {
    height: '100%',
    width: `${completed}%`,
    backgroundColor: bgcolor,
    borderRadius: 'inherit',
    textAlign: 'right'
  }

  const labelStyles = {
    padding: 5,
    color: 'white',
    fontWeight: 'bold'
  }

  return (
    <div style={containerStyles}>
      <div style={fillerStyles}>
        <span style={labelStyles}>{`${completed}%`}</span>
      </div>
    </div>
  );
};

export default ProgressBar;
Enter fullscreen mode Exit fullscreen mode

Nothing fancy. Mostly background colors and a border-radius.

Let’s test what we’ve developed.

import React from "react";
import "./App.css";
import ProgressBar from "./progress-bar.component";

const testData = [
  { bgcolor: "#6a1b9a", completed: 60 },
  { bgcolor: "#00695c", completed: 30 },
  { bgcolor: "#ef6c00", completed: 53 },
];

function App() {
  return (
    <div className="App">
      {testData.map((item, idx) => (
        <ProgressBar key={idx} bgcolor={item.bgcolor} completed={item.completed} />
      ))}
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Run the app and check what we’ve got in the browser.

three-bars-demo

And that’s it! The simple Progress Bar React component is ready!

BONUS. Adding animation.

Well, actually, to animate the progress bar movement it is sufficient to add just one line into the fillerStyles:

const fillerStyles = {
    ...
    transition: 'width 1s ease-in-out',
    ...
  }
Enter fullscreen mode Exit fullscreen mode

To demonstrate animation in action I’m going to create a function, which will randomly generate the completed prop value every 2 sec. This function will be place inside the useEffect hook.

function App() {
  const [completed, setCompleted] = useState(0);

  useEffect(() => {
    setInterval(() => setCompleted(Math.floor(Math.random() * 100) + 1), 2000);
  }, []);

  return (
    <div className="App">
      <ProgressBar bgcolor={"#6a1b9a"} completed={completed} />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

And that's the final result:

animated-demo

Conclusion

And that’s it! In this short blog post, I’ve described a step-by-step process of creating a custom Progress Bar React component. This component is fully customizable, so you can add any additional styling and functionality depending on your project needs.

The complete source code of the component is available in this GitHub repository

Also, you can use this component (with TypeScript support) as npm package.

Discussion (19)

pic
Editor guide
Collapse
jastuccio profile image
jastuccio • Edited

Nice progress bar. I am stuck passing props in a progress bar I am working on and may have found my solution in this example.

I think this one has some accessibility issues though. I'm a noob, but going to take a shot at the code based on step 3. This may not be right.

const ProgressBar = (props) => {
  const { bgcolor, completed } = props;

// styles...

  return (
    <div style={containerStyles}>
      <div style={fillerStyles}>
        <span
            style={labelStyles}>{`${completed}%`}
            role="progressbar"
            aria-valuenow=${completed}
            aria-valuemin="0"
            aria-valuemax="100"
       >
      </span>
      </div>
    </div>
  );
};

export default ProgressBar;
Enter fullscreen mode Exit fullscreen mode

MDN <progress> can be hard to style so we are using the progress role instead.

MDN - progressbar_role

Collapse
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Thank you for pointing this out! The component was written without accessibility at all. I should definitely correct this!

Collapse
jastuccio profile image
jastuccio

You're welcome. I think most of us learned HTML and CSS without accessibility as part of the code. I know I did. Accessibility was required for the progress bar I was building or I probably would not have thought to include it 🤦‍♂️

Collapse
jwhubert91 profile image
James Hubert

Hey just shouted you out in my recent dev.to post because I used your progress bar design: dev.to/jwhubert91/project-47-of-10...

Thanks again and please keep making these great tutorials!

Collapse
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Thank you very much, James!
And you are doing a great job on developing 100 React.js projects! Looking forward to reading about your next project!

Collapse
ohoroyoi profile image
ohoroyoi

this tutorial is fun thanks

Collapse
ramonak profile image
Collapse
niyongaboeric profile image
NiyongaboEric

With your help I was able to edit and write a custom progress bar I wanted. Thanks

Collapse
ramonak profile image
Collapse
shazena profile image
shazena

This was amazing! Thank you so much!!

Collapse
ramonak profile image
Collapse
izmarsel profile image
izmarsel

Thanks!! Used and modified your component. Really cool stuff!! Very useful for a personal project.

Collapse
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Happy that it was useful for you!

Collapse
ignore_you profile image
Alex

Thanks for this article, it helped me during building my own progress bar. Zhyve Belarus!

Collapse
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Thank you! Happy to help!

Zhyve vechna!!!

Collapse
hibaalaani profile image
Hiba Alaani

Thanks for this article,,,But how can i use the transition for the three progress ?

Collapse
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Hi Hiba! Could you please clarify what exactly are you trying to achieve? What do you mean by "three progress"? Sorry, I don't understand

Collapse
hibaalaani profile image
Hiba Alaani • Edited

Thanks for your replay....I was trying to make the progress have that transition but at beginning it doesn't work but then it's worked..
But Actually I have a question how can i calculate the co2 emissions by vanilla js is there any tutorial for that..

Thread Thread
ramonak profile image
Katsiaryna (Kate) Lupachova Author

Glad that the transition worked! As for the co2 emissions, sorry, but I can't help