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 CircularProgressbarWithChildren component enables placing arbitrary JSX content inside the progressbar with automatic centering and responsive sizing.
Wrapper component that combines a circular progressbar with arbitrary content placement inside the circle.
/**
* Wrapper component allowing arbitrary JSX content inside the progressbar
* @param props - Component props including all progressbar options plus children
* @returns React component with progressbar and centered content
*/
function CircularProgressbarWithChildren(props: CircularProgressbarWithChildrenProps): React.ReactElement;
interface CircularProgressbarWithChildrenProps extends CircularProgressbarWrapperProps {
/** Content to display inside the progressbar */
children?: React.ReactNode;
}
interface CircularProgressbarWrapperProps {
/** Current progress value (required) */
value: number;
/** Whether to display background circle */
background?: boolean;
/** Padding between background and path relative to total width */
backgroundPadding?: number;
/** Ratio of full circle diameter to use (0-1) */
circleRatio?: number;
/** CSS class names for SVG subcomponents */
classes?: {
root: string;
trail: string;
path: string;
text: string;
background: string;
};
/** CSS classes to apply to the SVG element */
className?: string;
/** Whether to rotate progressbar counterclockwise */
counterClockwise?: boolean;
/** Maximum value for progress range */
maxValue?: number;
/** Minimum value for progress range */
minValue?: number;
/** Width of circular line relative to total width (0-100) */
strokeWidth?: number;
/** Inline styles for SVG subcomponents */
styles?: CircularProgressbarStyles;
/** Text to display inside the progressbar (note: typically omitted when using children) */
text?: string;
}Usage Examples:
import React from 'react';
import { CircularProgressbarWithChildren } from 'react-circular-progressbar';
import 'react-circular-progressbar/dist/styles.css';
// Simple text content
function SimpleText() {
return (
<div style={{ width: 200, height: 200 }}>
<CircularProgressbarWithChildren value={75}>
<div style={{ fontSize: 16, fontWeight: 'bold' }}>
75%
</div>
</CircularProgressbarWithChildren>
</div>
);
}
// Multi-line content
function MultiLineContent() {
return (
<div style={{ width: 150, height: 150 }}>
<CircularProgressbarWithChildren value={88}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 18, fontWeight: 'bold' }}>88%</div>
<div style={{ fontSize: 12, color: '#666' }}>Complete</div>
</div>
</CircularProgressbarWithChildren>
</div>
);
}
// Custom content with icons
function WithIcon() {
return (
<div style={{ width: 100, height: 100 }}>
<CircularProgressbarWithChildren value={100}>
<div style={{ textAlign: 'center' }}>
<div>✓</div>
<div style={{ fontSize: 12 }}>Done</div>
</div>
</CircularProgressbarWithChildren>
</div>
);
}
// Interactive content
function InteractiveContent() {
const [value, setValue] = React.useState(50);
return (
<div style={{ width: 200, height: 200 }}>
<CircularProgressbarWithChildren value={value}>
<div style={{ textAlign: 'center' }}>
<div style={{ fontSize: 16, marginBottom: 8 }}>
{value}%
</div>
<button
onClick={() => setValue(v => Math.min(100, v + 10))}
style={{ fontSize: 12, padding: '4px 8px' }}
>
+10
</button>
</div>
</CircularProgressbarWithChildren>
</div>
);
}
// With image content
function WithImage() {
return (
<div style={{ width: 120, height: 120 }}>
<CircularProgressbarWithChildren
value={60}
styles={{
path: { stroke: '#3e98c7' },
trail: { stroke: '#d6d6d6' }
}}
>
<img
src="/avatar.jpg"
alt="User avatar"
style={{
width: 60,
height: 60,
borderRadius: '50%',
objectFit: 'cover'
}}
/>
</CircularProgressbarWithChildren>
</div>
);
}The children content is automatically positioned using flexbox centering within the progressbar bounds.
/**
* Content positioning system for children elements
* - Children are absolutely positioned within the progressbar
* - Automatic vertical and horizontal centering using flexbox
* - Full width and height available for content layout
* - Responsive sizing that adapts to progressbar dimensions
*/
interface ContentPositioning {
/** Container uses position: absolute with full dimensions */
container: {
position: 'absolute';
width: '100%';
height: '100%';
marginTop: '-100%';
display: 'flex';
flexDirection: 'column';
justifyContent: 'center';
alignItems: 'center';
};
}Layout Considerations:
// Content sizing best practices
function ResponsiveContent() {
return (
<div style={{ width: '300px', height: '300px' }}>
<CircularProgressbarWithChildren value={70}>
{/* Content should be sized relative to container */}
<div style={{
width: '80%', // Relative to progressbar size
textAlign: 'center',
padding: '10px'
}}>
<h3 style={{ margin: 0, fontSize: '1.2em' }}>Progress</h3>
<p style={{ margin: '5px 0 0 0', fontSize: '0.9em' }}>
70% Complete
</p>
</div>
</CircularProgressbarWithChildren>
</div>
);
}
// Complex nested content
function ComplexContent() {
return (
<div style={{ width: 250, height: 250 }}>
<CircularProgressbarWithChildren
value={85}
strokeWidth={6}
styles={{
path: { stroke: '#4ade80' },
trail: { stroke: '#e5e7eb' }
}}
>
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '8px'
}}>
<div style={{
width: 40,
height: 40,
backgroundColor: '#4ade80',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
fontSize: 18,
fontWeight: 'bold'
}}>
85
</div>
<div style={{ fontSize: 14, color: '#666' }}>
Tasks Complete
</div>
</div>
</CircularProgressbarWithChildren>
</div>
);
}Content inside the progressbar can be styled normally using CSS or inline styles.
Styling Guidelines:
// Typography and spacing recommendations
function StyledChildren() {
return (
<div style={{ width: 180, height: 180 }}>
<CircularProgressbarWithChildren value={92}>
<div style={{
// Center content and control text flow
textAlign: 'center',
// Use relative units for responsive sizing
fontSize: 'clamp(12px, 4vw, 18px)',
// Constrain content width to prevent overflow
maxWidth: '70%',
// Add padding for breathing room
padding: '8px',
// Control line spacing
lineHeight: 1.2
}}>
<div style={{ fontWeight: 'bold', marginBottom: '4px' }}>
92%
</div>
<div style={{ fontSize: '0.8em', opacity: 0.7 }}>
Upload Progress
</div>
</div>
</CircularProgressbarWithChildren>
</div>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-circular-progressbar