Building a Progress Bar component using ReactJS & Styled Components

Abinav Seelan
campvanilla

--

This article is available in video format:

In this article, we’ll be building a progress bar component in ReactJS and styled-components.

What will we be building today?

Final Output

The <ProgressBar /> component should do the following:

  1. Indicates the progress visually to the user via the colored bar.
  2. Shows the percentage numerically as a %
  3. Allow developers to configure the width of the bar and the color of the progress.

We’ll be building this component with semantic markup, using the Progress HTML element provided by Browsers.

The Progress HTML element

While we can build this component out using <div> tags, a more semantic tag that can be used here is the HTML Progress element.

The <progress /> HTML element does of lot of what we want out-of-the-box — it allows you to pass a value and a max to it and it automatically renders a bar denoting the percentage the given value is in the max.

Let’s see this in action. Say we have an <App /> component. Let’s render a <progress /> element in here with a value of 30 in a max of 100 (which is 30%)

The output for this would be,

How does browser support look for this element?

Looks pretty green to me. 🙂

So let’s build a React component called <ProgressBar /> that builds on top of what HTML provides us, allowing us to control other aspects such as styling (color and width) and rendering the percentage as text.

Adding the Boilerplate

To get some boilerplate out of the way, let’s create a React component called <ProgressBar /> that wraps around a <progress /> html element. We can also go ahead and start defining the props for this component as well:

Since the html element requires value and max, we can take those two values as props. We can also define these props in the PropTypesvalue is a required prop and for max we can define a defaultProp of 100.

And now we can use this component in the <App /> component from earlier.

And we get the following as the output,

Dynamic Updates

In a lot of cases, the progress bar would be required to show the progress of the user, which would change over time. Let’s simulate this using useState and a setInterval

In the above snippet, on mount, a useEffect is set up to run a setInterval. This setInterval runs every second and updates the value state variable, which is initialized as 0, by 10. Once it reaches 100, the interval is cleared.

Let’s see this in action now.

Rendering the percentage

Let’s now render the percentage on the right so that the user doesn’t always have to rely on the visual representation. 😅

We can render the percentage inside a <span />. Since we can’t return two elements from the <ProgressBar /> component, we can wrap the <progress /> element and the <span /> inside a <div /> tag.

The content of the <span /> would be the value divided by max, times 100.

Controlling the styling

The final piece in the list of requirements was allowing the consumer of <ProgressBar /> to control the color and width of the progress bar.

Here is where styled-components comes in. Let’s convert the encapsulating <div /> into a styled-component so that we can control the styling of both the progress and span elements.

Let’s configure the component to accept width and color from the consumer of the component.

Let’s allow the user to pass color and width, which will be string values with some defaultProps configured.

This color and width can be passed as props to the styled-component, where we can select the progress bar element and change the styling for it.

To control the width of the progress bar, we can select the progress bar using the progress[value] selector and assign the width for it as props.width.

Styling the color of the progress bar, however, requires the use of a couple of pseudo-selectors and undo-ing all the browser styling!

Let’s undo the browser’s default styling first. We can do this using the appearance: none property.

This should undo the browser’s default styling. Now to style the progress element, we have two pseudo selectors, ::-webkit-progress-bar and ::-webkit-progress-value that we can use to select and modify the background and the bar respectively.

In the above snippet, we’re setting the background and the bar’s height to 10px and re-adding the border-radius.

We can now funnel the user’s color prop as the background-color to the ::-webkit-progress-value selector.

With this wired up, let’s see the final output -

Conclusion

And there we have it — a <ProgressBar /> component built in React using semantic markup by leveraging the browser’s native progress element, while allowing developers to customize the design via styled-components. 🎉

~Fin~

If you found this helpful, do leave a 👏!

Stuck somewhere, need more help, or just want to say hi? Hit me up on Twitter and subscribe to my Youtube Channel. 🙃

--

--