A React progress component that provides an accessible way to display the completion progress of a task, typically displayed as a progress bar.
npx @tessl/cli install tessl/npm-radix-ui--react-progress@1.1.0A React progress component that provides an accessible way to display the completion progress of a task, typically displayed as a progress bar. Part of the Radix UI Primitives collection, it offers compound component architecture with Progress as the root container and ProgressIndicator for displaying the visual progress representation.
npm install @radix-ui/react-progressimport { Progress, ProgressIndicator } from "@radix-ui/react-progress";Import with types:
import {
Progress,
ProgressIndicator,
type ProgressProps,
type ProgressIndicatorProps
} from "@radix-ui/react-progress";Import with context scope creation:
import {
Progress,
ProgressIndicator,
createProgressScope
} from "@radix-ui/react-progress";Alternative component name imports:
import { Root, Indicator } from "@radix-ui/react-progress";For CommonJS:
const { Progress, ProgressIndicator } = require("@radix-ui/react-progress");Note: This package includes a 'use client' directive for Next.js App Router compatibility.
import * as React from "react";
import { Progress, ProgressIndicator } from "@radix-ui/react-progress";
// Determinate progress (specific value)
function App() {
const [progress, setProgress] = React.useState(65);
return (
<Progress value={progress} max={100} className="progress-root">
<ProgressIndicator
className="progress-indicator"
style={{ transform: `translateX(-${100 - progress}%)` }}
/>
</Progress>
);
}
// Indeterminate progress (loading state)
function LoadingProgress() {
return (
<Progress className="progress-root">
<ProgressIndicator className="progress-indicator loading" />
</Progress>
);
}The Progress component follows Radix UI's compound component pattern:
The main container component that provides context and accessibility attributes for the progress indicator.
interface ProgressProps extends React.ComponentPropsWithoutRef<'div'> {
/** The progress value. Use `null` or `undefined` for indeterminate progress */
value?: number | null | undefined;
/** The maximum progress value. Defaults to 100 */
max?: number;
/** Custom function to generate value label for accessibility. Defaults to percentage calculation */
getValueLabel?(value: number, max: number): string;
}
declare const Progress: React.ForwardRefExoticComponent<
ProgressProps & React.RefAttributes<HTMLDivElement>
>;Progress States:
Data Attributes:
data-state: Current progress state ('loading' | 'complete' | 'indeterminate')data-value: Current progress value (when not indeterminate)data-max: Maximum progress valueARIA Attributes:
role="progressbar"aria-valuemin="0"aria-valuemax: Set to max prop valuearia-valuenow: Current progress value (when not indeterminate)aria-valuetext: Generated value label for accessibilityVisual component that displays the actual progress representation and inherits state from the Progress context.
interface ProgressIndicatorProps extends React.ComponentPropsWithoutRef<'div'> {}
declare const ProgressIndicator: React.ForwardRefExoticComponent<
ProgressIndicatorProps & React.RefAttributes<HTMLDivElement>
>;The ProgressIndicator automatically receives the same data attributes as the Progress component:
data-state: Inherited progress statedata-value: Inherited progress valuedata-max: Inherited maximum value/** Alias for Progress component */
declare const Root: typeof Progress;
/** Alias for ProgressIndicator component */
declare const Indicator: typeof ProgressIndicator;For advanced use cases requiring multiple Progress components with isolated contexts.
/**
* Creates a scoped context for Progress components
* @returns Scope creation function for isolated Progress contexts
*/
declare function createProgressScope(): CreateScope;
/** Create scope function interface */
interface CreateScope {
scopeName: string;
(): ScopeHook;
}
/** Scope hook type returned by createProgressScope */
type ScopeHook = (scope: Scope) => { [__scopeProp: string]: Scope };
/** Scope type for context isolation */
type Scope<C = any> = { [scopeName: string]: React.Context<C>[] } | undefined;/** Props interface for Progress component */
interface ProgressProps extends React.ComponentPropsWithoutRef<'div'> {
value?: number | null | undefined;
max?: number;
getValueLabel?(value: number, max: number): string;
}
/** Props interface for ProgressIndicator component */
interface ProgressIndicatorProps extends React.ComponentPropsWithoutRef<'div'> {}
/** Internal progress state representation */
type ProgressState = 'indeterminate' | 'complete' | 'loading';
/** Element type for Progress component */
type ProgressElement = React.ComponentRef<'div'>;
/** Element type for ProgressIndicator component */
type ProgressIndicatorElement = React.ComponentRef<'div'>;The Progress component includes built-in validation with console warnings:
getValueLabel function is provided, defaults to percentage calculation (e.g., "65%" for value 65 of max 100).File Upload Progress:
function FileUploadProgress({ uploadProgress }: { uploadProgress: number | null }) {
return (
<Progress
value={uploadProgress}
max={100}
getValueLabel={(value, max) => `${value} of ${max} percent uploaded`}
>
<ProgressIndicator
style={{
transform: uploadProgress ? `translateX(-${100 - uploadProgress}%)` : 'translateX(-100%)',
transition: 'transform 0.3s ease'
}}
/>
</Progress>
);
}Multi-step Form Progress:
function FormProgress({ currentStep, totalSteps }: { currentStep: number; totalSteps: number }) {
const progress = (currentStep / totalSteps) * 100;
return (
<Progress
value={progress}
max={100}
getValueLabel={(value) => `Step ${currentStep} of ${totalSteps}`}
>
<ProgressIndicator
style={{ width: `${progress}%` }}
/>
</Progress>
);
}Loading State with Animation:
function LoadingProgress() {
return (
<Progress className="loading-progress">
<ProgressIndicator className="loading-indicator" />
</Progress>
);
}
// CSS for indeterminate animation
const styles = `
.loading-progress {
overflow: hidden;
}
.loading-indicator {
animation: loading 2s ease-in-out infinite;
}
@keyframes loading {
0% { transform: translateX(-100%); }
50% { transform: translateX(0%); }
100% { transform: translateX(100%); }
}
`;