syncfusion-react-progress-bar — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited syncfusion-react-progress-bar (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A comprehensive skill for implementing the Syncfusion React Progress Bar component for visual progress feedback, loading states, and task completion indicators.
Use this skill when you need to:
The Syncfusion React Progress Bar is a lightweight component that visualizes task progress in linear, circular, or semi-circular shapes. It supports multiple states (determinate, indeterminate, buffer) and features animations, customization, and full accessibility support.
Key Features:
📄 Read: references/getting-started.md
📄 Read: references/types-and-shapes.md
📄 Read: references/states-and-modes.md
📄 Read: references/customization-and-styling.md
📄 Read: references/animations-events-accessibility.md
📄 Read: references/api.md
ProgressBarComponent (see file).import { ProgressBarComponent } from '@syncfusion/ej2-react-progressbar';
function App() {
return (
<div>
{/* Linear Determinate Progress Bar */}
<ProgressBarComponent
id="linear"
type="Linear"
height="60"
value={75}
animation={{
enable: true,
duration: 2000,
delay: 0
}}
/>
{/* Circular Progress Bar */}
<ProgressBarComponent
id="circular"
type="Circular"
height="160px"
value={60}
/>
{/* Indeterminate Loading Spinner */}
<ProgressBarComponent
id="indeterminate"
type="Linear"
height="60"
isIndeterminate={true}
animation={{
enable: true,
duration: 2000,
delay: 0
}}
/>
</div>
);
}
export default App;<ProgressBarComponent
id="upload"
type="Linear"
value={uploadPercentage}
showProgressValue={true}
progressValueFormat="N0 '%'"
/><ProgressBarComponent
id="spinner"
type="Circular"
isIndeterminate={true}
height="100px"
/><ProgressBarComponent
id="buffer"
type="Linear"
value={40}
secondaryProgress={80}
height="60"
/><ProgressBarComponent
id="task"
type="Linear"
value={taskCompletionPercentage}
showProgressValue={true}
animation={{
enable: true,
duration: 1500
}}
/>| Prop | Type | Default | Purpose | ||
|---|---|---|---|---|---|
id | string | - | Unique identifier for component | ||
type | "Linear" \ | "Circular" \ | "Semicircle" | "Linear" | Shape of progress bar |
value | number | 0 | Current progress value (0-100) | ||
secondaryProgress | number | 0 | Secondary/buffer progress value | ||
isIndeterminate | boolean | false | Indeterminate/loading mode | ||
height | string | "100%" | Height of progress bar (CSS value) | ||
width | string | "100%" | Width of progress bar (CSS value) | ||
showProgressValue | boolean | false | Display percentage text |
| Prop | Type | Default | Purpose |
|---|---|---|---|
animation | AnimationModel | - | Animation config: { enable, duration, delay } |
progressColor | string | - | Color for progress fill (CSS color) |
trackColor | string | - | Color for track background |
progressThickness | number | 4 | Progress bar thickness (pixels) |
trackThickness | number | 4 | Track thickness (pixels) |
isStriped | boolean | false | Striped pattern appearance |
isGradient | boolean | false | Gradient fill effect |
cssClass | string | - | Custom CSS class for styling |
| Prop | Type | Default | Purpose | |
|---|---|---|---|---|
cornerRadius | "Round" \ | "Auto" | "Auto" | Corner style for ends |
enableRtl | boolean | false | Right-to-left layout | |
enablePieProgress | boolean | false | Pie view for circular type | |
enableProgressSegments | boolean | false | Segmented progress rendering | |
segmentCount | number | 1 | Number of segments | |
rangeColors | RangeColorModel[] | - | Colors for different ranges | |
minimum | number | 0 | Minimum progress value | |
maximum | number | 100 | Maximum progress value |
| Prop | Type | Default | Purpose |
|---|---|---|---|
progressValueFormat | string | "N0 '%'" | Format for value display (e.g., "N2 '%'") |
labelOnTrack | boolean | true | Show label on the track |
labelStyle | FontModel | - | Font styling for label |
When to use each:
const [uploadProgress, setUploadProgress] = useState(0);
<ProgressBarComponent
type="Linear"
value={uploadProgress}
showProgressValue={true}
progressValueFormat="N0 '%'"
height="30"
animation={{ enable: true, duration: 500 }}
/>Best Practices:
secondaryProgress for pre-fetched bytes<ProgressBarComponent
type="Circular"
isIndeterminate={true}
height="100px"
animation={{ enable: true, duration: 2000 }}
/>Best Practices:
isIndeterminate={true} until operation completesconst [processProgress, setProcessProgress] = useState(0);
const totalItems = 100;
useEffect(() => {
processItems().then(processed => {
setProcessProgress((processed / totalItems) * 100);
});
}, []);
<ProgressBarComponent
type="Linear"
value={processProgress}
showProgressValue={true}
height="30"
/>Best Practices:
const [processedItems, setProcessedItems] = useState(30);
const [queuedItems, setQueuedItems] = useState(75);
const totalItems = 100;
<ProgressBarComponent
type="Linear"
value={(processedItems / totalItems) * 100}
secondaryProgress={(queuedItems / totalItems) * 100}
height="30"
/>Best Practices:
const steps = ['Validation', 'Processing', 'Upload', 'Confirmation'];
const [currentStep, setCurrentStep] = useState(0);
const progress = ((currentStep + 1) / steps.length) * 100;
<ProgressBarComponent
type="Linear"
value={progress}
showProgressValue={true}
height="30"
/>
<div>
{steps.map((step, i) => (
<div key={i}>
{step} {i === currentStep ? '🔄' : i < currentStep ? '✓' : '⏳'}
</div>
))}
</div>Best Practices:
import { useState, useEffect } from 'react';
import { ProgressBarComponent } from '@syncfusion/ej2-react-progressbar';
function ProgressManager() {
const [progress, setProgress] = useState(0);
const [isProcessing, setIsProcessing] = useState(false);
useEffect(() => {
if (!isProcessing) return;
const interval = setInterval(() => {
setProgress(prev => {
if (prev >= 100) {
setIsProcessing(false);
return 100;
}
return prev + Math.random() * 15;
});
}, 500);
return () => clearInterval(interval);
}, [isProcessing]);
return (
<div>
<ProgressBarComponent
type="Linear"
value={progress}
showProgressValue={true}
/>
<button
onClick={() => { setProgress(0); setIsProcessing(true); }}
disabled={isProcessing}
>
{isProcessing ? 'Processing...' : 'Start'}
</button>
</div>
);
}
export default ProgressManager;// Real-time updates (no animation for smoothness)
animation={{ enable: false }}
// User interactions (quick feedback)
animation={{ enable: true, duration: 300, delay: 0 }}
// Page loads (smooth transition)
animation={{ enable: true, duration: 1500, delay: 0 }}
// Cascading effects (staggered)
animation={{ enable: true, duration: 1000, delay: 200 }}
// Loading spinners (continuous)
animation={{ enable: true, duration: 2000 }}function ConditionalProgress() {
const [state, setState] = useState('idle'); // idle | loading | success | error
const [value, setValue] = useState(0);
const getProgressType = () => {
if (state === 'loading') return 'Circular';
return 'Linear';
};
return (
<>
{state === 'loading' && (
<ProgressBarComponent
type={getProgressType()}
isIndeterminate={state === 'loading'}
height="100px"
/>
)}
{state === 'success' && (
<div style={{ color: 'green' }}>✓ Complete</div>
)}
{state === 'error' && (
<div style={{ color: 'red' }}>✗ Error occurred</div>
)}
</>
);
}
export default ConditionalProgress;function ProgressWithEvents() {
const handleStart = () => {
console.log('Progress started');
analytics.track('progress_started');
};
const handleComplete = () => {
console.log('Progress completed');
analytics.track('progress_completed');
showNotification('Task completed!');
};
const handleValueChange = (args) => {
console.log(`Progress: ${args.value}%`);
// Milestone tracking
if (args.value === 50) {
analytics.track('progress_midpoint');
}
};
return (
<ProgressBarComponent
type="Linear"
value={75}
progressStart={handleStart}
progressComplete={handleComplete}
valueChanged={handleValueChange}
/>
);
}
export default ProgressWithEvents;function ResponsiveProgress() {
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth < 768);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<ProgressBarComponent
type={isMobile ? 'Semicircle' : 'Linear'}
value={65}
height={isMobile ? '100px' : '40'}
showProgressValue={true}
/>
);
}
export default ResponsiveProgress;async function uploadWithRetry(file, maxRetries = 3) {
const [attempts, setAttempts] = useState(0);
const [progress, setProgress] = useState(0);
const [error, setError] = useState(null);
for (let i = 0; i < maxRetries; i++) {
try {
setAttempts(i + 1);
const result = await uploadFile(file, (p) => setProgress(p));
return result;
} catch (err) {
if (i === maxRetries - 1) {
setError(`Failed after ${maxRetries} attempts`);
throw err;
}
// Retry with exponential backoff
await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
}
}
}import { useQuery } from '@tanstack/react-query';
function DataProcessing() {
const { data, isLoading, progress } = useQuery({
queryKey: ['processData'],
queryFn: async ({ signal }) => {
// Process with progress tracking
}
});
return (
<ProgressBarComponent
isIndeterminate={isLoading}
value={progress || 0}
/>
);
}import { useSelector, useDispatch } from 'react-redux';
function ReduxProgress() {
const { progress, isLoading } = useSelector(state => state.upload);
const dispatch = useDispatch();
return (
<ProgressBarComponent
value={progress}
isIndeterminate={isLoading}
progressComplete={() => dispatch(resetProgress())}
/>
);
}~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.