A circular progress indicator component built with React and SVG
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The buildStyles utility function provides a convenient way to generate comprehensive style objects with common customization options like colors, transitions, and rotations.
Utility function for generating styles object with common progressbar customization options.
/**
* Generate styles object for progressbar customization
* @param options - Style customization options
* @returns CircularProgressbarStyles object for use with styles prop
*/
function buildStyles(options: {
/** Number of turns for rotation (0-1). 0.25 = quarter turn, 0.5 = half turn */
rotation?: number;
/** Stroke line cap style ('butt' | 'round' | 'square') */
strokeLinecap?: any;
/** Color for text element */
textColor?: string;
/** Size for text element (CSS font-size value) */
textSize?: string | number;
/** Color for progress path */
pathColor?: string;
/** CSS transition property for path animations */
pathTransition?: string;
/** Duration in seconds for path transitions */
pathTransitionDuration?: number;
/** Color for background trail */
trailColor?: string;
/** Color for background circle */
backgroundColor?: string;
}): CircularProgressbarStyles;
interface CircularProgressbarStyles {
/** Styles for root SVG element */
root?: React.CSSProperties;
/** Styles for background trail path */
trail?: React.CSSProperties;
/** Styles for progress path */
path?: React.CSSProperties;
/** Styles for text element */
text?: React.CSSProperties;
/** Styles for background circle */
background?: React.CSSProperties;
}Usage Examples:
import React from 'react';
import { CircularProgressbar, buildStyles } from 'react-circular-progressbar';
import 'react-circular-progressbar/dist/styles.css';
// Basic color customization
function CustomColors() {
return (
<div style={{ width: 150, height: 150 }}>
<CircularProgressbar
value={75}
text="75%"
styles={buildStyles({
pathColor: '#f88',
textColor: '#f88',
trailColor: '#d6d6d6'
})}
/>
</div>
);
}
// With rotation and rounded caps
function RotatedProgress() {
return (
<div style={{ width: 200, height: 200 }}>
<CircularProgressbar
value={60}
text="60%"
styles={buildStyles({
rotation: 0.25, // Quarter turn (start from top)
strokeLinecap: 'round',
pathColor: '#3e98c7',
trailColor: '#d6d6d6',
textColor: '#3e98c7'
})}
/>
</div>
);
}
// Animated progress with transition
function AnimatedProgress() {
const [value, setValue] = React.useState(0);
React.useEffect(() => {
const timer = setInterval(() => {
setValue(v => (v >= 100 ? 0 : v + 10));
}, 500);
return () => clearInterval(timer);
}, []);
return (
<div style={{ width: 180, height: 180 }}>
<CircularProgressbar
value={value}
text={`${value}%`}
styles={buildStyles({
pathTransition: 'stroke-dashoffset 0.5s ease 0s',
pathColor: '#00d4aa',
trailColor: '#d6d6d6',
textColor: '#00d4aa'
})}
/>
</div>
);
}
// Custom text size and background
function CustomStyling() {
return (
<div style={{ width: 220, height: 220 }}>
<CircularProgressbar
value={88}
text="88%"
background={true}
styles={buildStyles({
pathColor: '#ff6b6b',
textColor: '#ff6b6b',
trailColor: 'transparent',
backgroundColor: '#f8f9fa',
textSize: '24px'
})}
/>
</div>
);
}Control colors for all visual elements of the progressbar.
/**
* Color customization options
*/
interface ColorOptions {
/** Color for the progress path (e.g., '#3e98c7', 'rgb(62, 152, 199)', 'blue') */
pathColor?: string;
/** Color for the background trail (e.g., '#d6d6d6', 'rgba(0,0,0,0.1)') */
trailColor?: string;
/** Color for the text element (e.g., '#333', 'currentColor') */
textColor?: string;
/** Color for the background circle when background prop is true */
backgroundColor?: string;
}Color Examples:
// Gradient-like effect using multiple components
function GradientEffect() {
return (
<div style={{ width: 160, height: 160, position: 'relative' }}>
{/* Background layer */}
<CircularProgressbar
value={100}
styles={buildStyles({
pathColor: '#e3f2fd',
trailColor: 'transparent'
})}
/>
{/* Foreground layer */}
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }}>
<CircularProgressbar
value={70}
text="70%"
styles={buildStyles({
pathColor: '#2196f3',
trailColor: 'transparent',
textColor: '#2196f3'
})}
/>
</div>
</div>
);
}
// Theme-based colors
function ThemedColors() {
const theme = {
success: '#4caf50',
warning: '#ff9800',
error: '#f44336',
info: '#2196f3'
};
return (
<div style={{ display: 'flex', gap: '20px' }}>
{Object.entries(theme).map(([type, color]) => (
<div key={type} style={{ width: 100, height: 100 }}>
<CircularProgressbar
value={75}
text={type}
styles={buildStyles({
pathColor: color,
textColor: color,
trailColor: '#f0f0f0',
textSize: '12px'
})}
/>
</div>
))}
</div>
);
}Control animations and transitions for smooth visual effects.
/**
* Animation and transition options
*/
interface AnimationOptions {
/** CSS transition property for path element (e.g., 'stroke-dashoffset 0.5s ease') */
pathTransition?: string;
/** Duration in seconds for path transitions (generates transition-duration CSS) */
pathTransitionDuration?: number;
}Animation Examples:
// Easing variations
function EasingExamples() {
const easings = [
'ease',
'ease-in',
'ease-out',
'ease-in-out',
'cubic-bezier(0.4, 0, 0.2, 1)'
];
return (
<div style={{ display: 'flex', gap: '15px' }}>
{easings.map((easing, index) => (
<div key={easing} style={{ width: 80, height: 80 }}>
<CircularProgressbar
value={(index + 1) * 20}
styles={buildStyles({
pathTransition: `stroke-dashoffset 1s ${easing}`,
pathColor: '#9c27b0'
})}
/>
</div>
))}
</div>
);
}
// Delayed transitions
function DelayedTransitions() {
const [trigger, setTrigger] = React.useState(false);
return (
<div>
<button onClick={() => setTrigger(!trigger)}>
Toggle Progress
</button>
<div style={{ width: 200, height: 200, marginTop: 20 }}>
<CircularProgressbar
value={trigger ? 90 : 10}
text={`${trigger ? 90 : 10}%`}
styles={buildStyles({
pathTransition: 'stroke-dashoffset 2s ease-in-out 0.5s', // 0.5s delay
pathColor: '#ff5722',
textColor: '#ff5722'
})}
/>
</div>
</div>
);
}Customize text appearance and progressbar orientation.
/**
* Typography and rotation options
*/
interface TypographyRotationOptions {
/** Text size using any CSS font-size value */
textSize?: string | number;
/** Number of turns for rotation (0-1 range) */
rotation?: number;
/** Stroke line cap style for path ends */
strokeLinecap?: any;
}Typography and Rotation Examples:
// Text size variations
function TextSizes() {
const sizes = ['12px', '16px', '20px', '1.5em', '2rem'];
return (
<div style={{ display: 'flex', gap: '20px', alignItems: 'center' }}>
{sizes.map(size => (
<div key={size} style={{ width: 100, height: 100 }}>
<CircularProgressbar
value={50}
text="50%"
styles={buildStyles({
textSize: size,
pathColor: '#795548',
textColor: '#795548'
})}
/>
<div style={{ textAlign: 'center', fontSize: '12px', marginTop: '5px' }}>
{size}
</div>
</div>
))}
</div>
);
}
// Rotation variations
function RotationVariations() {
const rotations = [0, 0.125, 0.25, 0.375, 0.5];
return (
<div style={{ display: 'flex', gap: '20px' }}>
{rotations.map(rotation => (
<div key={rotation} style={{ width: 100, height: 100 }}>
<CircularProgressbar
value={75}
text={`${rotation * 360}°`}
styles={buildStyles({
rotation,
strokeLinecap: 'round',
pathColor: '#607d8b',
textColor: '#607d8b',
textSize: '12px'
})}
/>
</div>
))}
</div>
);
}
// Combined styling
function AdvancedStyling() {
return (
<div style={{ width: 250, height: 250 }}>
<CircularProgressbar
value={82}
text="82%"
styles={buildStyles({
rotation: 0.25,
strokeLinecap: 'round',
textSize: '28px',
pathTransitionDuration: 0.75,
pathColor: `url(#gradient)`,
textColor: '#1976d2',
trailColor: '#e1f5fe'
})}
/>
</div>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-circular-progressbar