Introduction

ProgressBar component enhance websites by providing visual feedback for file uploads, form submissions, content loading, task completion, downloads/updates, and page scrolling. They improve the user experience, engagement, and interface, keeping users informed and motivated in a concise and intuitive manner. By incorporating our ProgressBar component, you can elevate your website's user experience to new heights, adding a touch of interactivity and visual appeal. With progress indicators tailored to various scenarios, your website will become more engaging and provide a seamless and delightful user journey.

ProgressBar Component Documentation

The ProgressBar component is used to display a progress bar with customizable styles.

Usage

To use the ProgressBar component, follow these steps:

  1. Install the required dependencies:
npm install @locoworks/reusejs-react-progress-bar

or

yarn add @locoworks/reusejs-react-progress-bar
  1. Import ProgressBar:
import { ProgressBar,CircularProgressBar } from "@locoworks/reusejs-react-progress-bar";

Props for ProgressBar

The ProgressBar component accepts the following props:

  • progressClasses (optional): A string of additional CSS classes to be applied to the progress bar. These classes will be merged with the default progress bar classes. (Accepts: Tailwind Classes and CSSProperties)
  • progressContainerClasses (optional): A string of additional CSS classes to be applied to the progress bar container. These classes will be merged with the default progress bar container classes. (Accepts: Tailwind Classes and CSSProperties)
  • progressInterval (required): The interval (in milliseconds) at which the progress should be updated.
  • running (optional): A boolean value indicating whether the progress bar is currently running or paused. To start the progress, this value must be set to true. (Default: false)
  • defaultProgress (required): The default progress value (between 0 and 100) to be displayed when the progress bar is initially rendered. (Default: undefined)
  • totalFileSize (optional): The total file size in bytes. It is used to calculate the progress percentage based on the processed file size. (Default: 0)
  • processedFileSize (optional): The processed file size in bytes. It is used to calculate the progress.
  • progressLoop (optional): If true it will updated every time the progress even if it reaches to hundred.(Default Value is false after reaching 100 it will do nothing. If true, after reaching 100 it will wait for change in processedFile and if changes happend it will recalculate the the progress and return it.)

Props for CircularProgressBar

The CircularProgressBar accepts following 5 additional props apart from above:

  • radius (optional as number): The radius of the circular progress bar (default: 95).
  • circleRadiusInPercentage (optional): The radius of the circular progress bar in percentage (both radius and circleRadiusInPercentage need to be passed together ex: radius=55 , circleRadiusInPercentage="25%").
  • circleContainerClasses (optional): This accepts either a string as CSS classes or an object of CSS properties to apply the styles on ProgressContainer.
  • innerCircleClasses (optional as string): This accepts either a string as CSS classes or an object of CSS properties to apply the styles on InnerCircle which is initially grey colour.
  • outerCircleClasses (required must pass stroke-color): This accepts either a string as CSS classes or an object of CSS properties to apply the styles on OuterCircle which shows Progress as in different colour.
  • progressLoop (optional): If true it will updated every time the progress even if it reaches to hundred.(Default Value is false after reaching 100 it will do nothing. If true, after reaching 100 it will wait for change in processedFile and if changes happend it will recalculate the the progress and return it.)

Note

  • To use Circular ProgressBar You have to import CircularProgressBar.
  • To Adjust Circular ProgressBar Size you need to pass two props (radius,circleRadiousInPercentage,progressClasses).
  • To get better understanding for these props refer to Circular ProgressBar examples and Check code.

Examples

ProgressBar with a graphical edge

progress Value 0 %
import React, { useState } from "react";
import { ProgressBar } from "@locoworks/reusejs-react-progress-bar";
import { ReuseButton } from "@locoworks/reusejs-react-button";

const Progress = () => {
	const [running, setRunning] = useState<boolean>(false);
	return (
		<div className="flex items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
			<div className="w-full h-72 flex flex-col justify-center items-center mx-80">
				<ProgressBar
					progressInterval={2000}
					running={running}
					defaultProgress={0}
					progressContainerClasses="bg-gray-300 h-6 flex rounded-none"
					progressClasses="h-full rounded-none"
					progressText={(progress: number) => `progress Value ${progress} %`}
				/>

				<ReuseButton
					className="bg-blue-500 text-white font-bold text-2xl text-center mt-20 px-6 flex"
					onClick={() => setRunning(!running)}
				>
					{running ? "Pause" : "Play"}
				</ReuseButton>
			</div>
		</div>
	);
};

export default Progress;

Note:

  • Graphical edge refers to the boundaries or transitions between different regions or features in an image, and it plays a crucial role in computer graphics and image processing tasks.
  • Here Graphical edge refers to the edges of the ProgressBar or corner of the ProgressBar.

ProgressBar without a graphical edge

import React, { useState } from "react";
import { ProgressBar } from "@locoworks/reusejs-react-progress-bar";
import { ReuseButton } from "@locoworks/reusejs-react-button";

const RoundedProgress = () => {
	const [running, setRunning] = useState<boolean>(false);
	return (
		<div className="flex items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
			<div className="w-full h-72 flex flex-col justify-center items-center mx-80">
				<ProgressBar
					progressInterval={2000}
					running={running}
					defaultProgress={0}
					progressContainerClasses="bg-gray-300 h-6 flex"
					progressClasses="h-full"
				/>
				<ReuseButton
					className="bg-blue-500 text-white font-bold text-2xl text-center mt-20 px-6 flex"
					onClick={() => setRunning(!running)}
				>
					{running ? "Pause" : "Play"}
				</ReuseButton>
			</div>
		</div>
	);
};

export default RoundedProgress;

Download File ProgressBar

Downloaded 0%
import React, { useState, useRef, useEffect } from "react";
import { ProgressBar } from "@locoworks/reusejs-react-progress-bar";
import { ReuseButton } from "@locoworks/reusejs-react-button";

const DownloadFile = () => {
	const [running, setRunning] = useState<boolean>(false);
	const [processedFile, setProcessedFile] = useState<number>(0);

	const processedFileRef = useRef<NodeJS.Timeout | null>(null);
	const StartUploadDownload = () => {
		clearInterval(processedFileRef.current as NodeJS.Timeout);
		processedFileRef.current = setInterval(() => {
			setProcessedFile((previousValue) => {
				return previousValue + 10;
			});
		}, 10);
	};

	useEffect(() => {
		if (processedFile === 5000) {
			clearInterval(processedFileRef.current as NodeJS.Timeout);
		}
	}, [processedFile]);
	return (
		<div className="flex items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
			<div className="w-full h-72 flex flex-col justify-center items-center mx-80">
				<ProgressBar
					progressInterval={2000}
					running={running}
					defaultProgress={0}
					progressContainerClasses="bg-gray-200 h-6 flex"
					progressClasses="bg-green-600 h-full"
					processedFileSize={processedFile}
					totalFileSize={5000}
					progressText={(progress: number) => `Downloaded ${progress}%`}
					progressTextClasses="text-xl font-normal justify-self-center"
				/>
				<ReuseButton
					className="bg-blue-500 text-white font-bold text-2xl text-center mt-20 px-6 flex"
					onClick={() => {
						setRunning(true);
						StartUploadDownload();
					}}
				>
					Start File Download
				</ReuseButton>
			</div>
		</div>
	);
};

export default DownloadFile;

Upload File ProgressBar

Uploaded 0%
import React, { useState, useRef, useEffect } from "react";
import { ProgressBar } from "@locoworks/reusejs-react-progress-bar";
import { ReuseButton } from "@locoworks/reusejs-react-button";

const UploadFile = () => {
	const [running, setRunning] = useState<boolean>(false);
	const [processedFile, setProcessedFile] = useState<number>(0);

	const processedFileRef = useRef<NodeJS.Timeout | null>(null);
	const StartUploadDownload = () => {
		clearInterval(processedFileRef.current as NodeJS.Timeout);
		processedFileRef.current = setInterval(() => {
			setProcessedFile((previousValue) => {
				return previousValue + 10;
			});
		}, 100);
	};

	useEffect(() => {
		if (processedFile === 5000) {
			clearInterval(processedFileRef.current as NodeJS.Timeout);
		}
	}, [processedFile]);
	return (
		<div className="flex items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
			<div className="w-full h-72 flex flex-col justify-center items-center mx-80">
				<ProgressBar
					progressInterval={2000}
					running={running}
					defaultProgress={0}
					progressContainerClasses="bg-gray-500 h-6 flex"
					progressClasses="bg-yellow-600 h-full"
					processedFileSize={processedFile}
					totalFileSize={5000}
					progressText={(progress: number) => `Uploaded ${progress}%`}
					progressTextClasses="text-xl font-normal justify-self-center"
				/>
				<ReuseButton
					className="bg-blue-500 text-white font-bold text-2xl text-center mt-20 px-6 flex"
					onClick={() => {
						setRunning(true);
						StartUploadDownload();
					}}
				>
					Start File Upload
				</ReuseButton>
			</div>
		</div>
	);
};

export default UploadFile;

Circular ProgressBar

Progress One 0 %
0%
Low Risk
import React, { useEffect, useRef, useState } from "react";
import { CircularProgressBar } from "@locoworks/reusejs-react-progress-bar";
import { ReuseButton } from "@locoworks/reusejs-react-button";

const CircularProgress = () => {
	const [runningOne, setRunningOne] = useState<boolean>(false);
	const [runningTwo, setRunningTwo] = useState<boolean>(false);
	const [runningThree, setRunningThree] = useState<boolean>(false);
	const [processedFile, setProcessedFile] = useState<number>(0);

	const processedFileRef = useRef<NodeJS.Timeout | null>(null);
	const StartUploadDownload = () => {
		clearInterval(processedFileRef.current as NodeJS.Timeout);
		processedFileRef.current = setInterval(() => {
			setProcessedFile((previousValue) => {
				return previousValue + 10;
			});
		}, 10);
	};

	useEffect(() => {
		if (processedFile === 5000) {
			clearInterval(processedFileRef.current as NodeJS.Timeout);
		}
	}, [processedFile]);
	return (
		<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
			<div className="flex justify-evenly w-full">
				<CircularProgressBar
					progressInterval={2000}
					running={runningOne}
					defaultProgress={0}
					progressText={(progress: number) => `Progress One ${progress} %`}
					progressTextClasses={"text-center font-extrabold"}
					outerCircleClasses={"stroke-green-500"}
				/>
				<CircularProgressBar
					progressInterval={2000}
					running={runningTwo}
					defaultProgress={0}
					radius={55}
					circleRadiusInPercentage="25%"
					totalFileSize={5000}
					processedFileSize={processedFile}
					outerCircleClasses={"stroke-yellow-500"}
					progressTextClasses={"text-center font-bold absolute"}
				/>
				<CircularProgressBar
					progressInterval={4000}
					running={runningThree}
					defaultProgress={0}
					radius={75}
					outerCircleClasses={{
						stroke: "red",
					}}
					circleRadiusInPercentage="35%"
					progressText={(progress: number) => {
						return progress >= 0 && progress <= 33
							? "Low Risk"
							: progress > 33 && progress <= 66
							? "Medium Risk"
							: "High Risk";
					}}
					progressTextClasses={"text-center text-2xl"}
				/>
			</div>

			<div className="flex w-full justify-around items-center">
				<ReuseButton
					className="bg-blue-500 text-white font-bold text-xl text-center mt-20 px-6 flex"
					onClick={() => {
						setRunningOne(!runningOne);
					}}
				>
					{runningOne ? "Pause" : "Play"}
				</ReuseButton>
				<ReuseButton
					className="bg-blue-500 text-white font-bold text-xl text-center mt-20 px-6 flex"
					onClick={() => {
						setRunningTwo(true);
						StartUploadDownload();
					}}
				>
					{runningTwo ? "Pause" : "Play"}
				</ReuseButton>
				<ReuseButton
					className="bg-blue-500 text-white font-bold text-xl text-center mt-20 px-6 flex"
					onClick={() => {
						setRunningThree(!runningThree);
					}}
				>
					{runningThree ? "Pause" : "Play"}
				</ReuseButton>
			</div>
		</div>
	);
};

export default CircularProgress;

PageScrollProgress

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

import React, { useState, useEffect, useRef } from "react";
import { useProgress } from "@locoworks/reusejs-toolkit-react-hooks";

const PageScrollProgress = () => {
	const [scrollValue, setScrollValue] = useState<number>(0);
	const [parentscrollHeight, setParentScrollHeight] = useState<
		number | undefined
	>(0);

	const scrollRef = useRef<HTMLDivElement | null>(
		null,
	) as React.RefObject<HTMLDivElement>;
	let scrollContainer = scrollRef.current;

	const handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
		const targetElement = event.target as HTMLDivElement;
		const scrollTop = targetElement.scrollTop;
		setScrollValue(scrollTop);
	};

	const { progress } = useProgress({
		totalFileSize: parentscrollHeight,
		processedFileSize: scrollValue,
		running: false,
		progressLoop: true, // to Implement PageScroll Progress Feature it must be passed as true.
	});

	useEffect(() => {
		scrollContainer = scrollRef.current;
		const totalHeight: number = Number(scrollContainer?.scrollHeight);
		const viewAreaHeight: number = Number(scrollContainer?.offsetHeight);
		setParentScrollHeight(totalHeight - viewAreaHeight);
	}, []);

	return (
		<div className="flex relative items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
			<div
				className="flex absolute bg-red-500 left-0 top-0 h-1"
				style={{ width: `${progress}%` }}
			></div>
			<div
				className="relative flex flex-col w-full max-h-96 items-center overflow-x-auto"
				onScroll={handleScroll}
				ref={scrollRef}
			>
				<div className="flex flex-col text-center justify-center items-center w-full">
					<p className="flex text-center font-semibold text-xl  my-2">
						{`Lorem Ipsum is simply dummy text of the printing and typesetting
						industry. Lorem Ipsum has been the industry's standard dummy text
						ever since the 1500s, when an unknown printer took a galley of type
						and scrambled it to make a type specimen book. It has survived not
						only five centuries, but also the leap into electronic typesetting,
						remaining essentially unchanged. It was popularised in the 1960s
						with the release of Letraset sheets containing Lorem Ipsum passages,
						and more recently with desktop publishing software like Aldus
						PageMaker including versions of Lorem Ipsum.`}
					</p>
					<p className="flex text-center font-semibold text-xl  my-2">
						{`Lorem Ipsum is simply dummy text of the printing and typesetting
						industry. Lorem Ipsum has been the industry's standard dummy text
						ever since the 1500s, when an unknown printer took a galley of type
						and scrambled it to make a type specimen book. It has survived not
						only five centuries, but also the leap into electronic typesetting,
						remaining essentially unchanged. It was popularised in the 1960s
						with the release of Letraset sheets containing Lorem Ipsum passages,
						and more recently with desktop publishing software like Aldus
						PageMaker including versions of Lorem Ipsum.`}
					</p>
					<p className="flex text-center font-semibold text-xl  my-2">
						{`Lorem Ipsum is simply dummy text of the printing and typesetting
						industry. Lorem Ipsum has been the industry's standard dummy text
						ever since the 1500s, when an unknown printer took a galley of type
						and scrambled it to make a type specimen book. It has survived not
						only five centuries, but also the leap into electronic typesetting,
						remaining essentially unchanged. It was popularised in the 1960s
						with the release of Letraset sheets containing Lorem Ipsum passages,
						and more recently with desktop publishing software like Aldus
						PageMaker including versions of Lorem Ipsum.`}
					</p>
					<p className="flex text-center font-semibold text-xl  my-2">
						{`Lorem Ipsum is simply dummy text of the printing and typesetting
						industry. Lorem Ipsum has been the industry's standard dummy text
						ever since the 1500s, when an unknown printer took a galley of type
						and scrambled it to make a type specimen book. It has survived not
						only five centuries, but also the leap into electronic typesetting,
						remaining essentially unchanged. It was popularised in the 1960s
						with the release of Letraset sheets containing Lorem Ipsum passages,
						and more recently with desktop publishing software like Aldus
						PageMaker including versions of Lorem Ipsum.`}
					</p>
					<p className="flex text-center font-semibold text-xl  my-2">
						{`Lorem Ipsum is simply dummy text of the printing and typesetting
						industry. Lorem Ipsum has been the industry's standard dummy text
						ever since the 1500s, when an unknown printer took a galley of type
						and scrambled it to make a type specimen book. It has survived not
						only five centuries, but also the leap into electronic typesetting,
						remaining essentially unchanged. It was popularised in the 1960s
						with the release of Letraset sheets containing Lorem Ipsum passages,
						and more recently with desktop publishing software like Aldus
						PageMaker including versions of Lorem Ipsum.`}
					</p>
					<p className="flex text-center font-semibold text-xl  my-2">
						{`Lorem Ipsum is simply dummy text of the printing and typesetting
						industry. Lorem Ipsum has been the industry's standard dummy text
						ever since the 1500s, when an unknown printer took a galley of type
						and scrambled it to make a type specimen book. It has survived not
						only five centuries, but also the leap into electronic typesetting,
						remaining essentially unchanged. It was popularised in the 1960s
						with the release of Letraset sheets containing Lorem Ipsum passages,
						and more recently with desktop publishing software like Aldus
						PageMaker including versions of Lorem Ipsum.`}
					</p>
				</div>
			</div>
		</div>
	);
};

export default PageScrollProgress;