5.4 KiB
Progress
(no submodules)
- progress.variants — `progressVariants` is the cva c…-
progress.variants —
progressVariantsis the cva config that powers the<Progress>chassis component (paired with `progressIndicatorVari… -
progress.variants —
progressVariantsis the cva c… -
progress.variants —
progressVariantsis the cva config that powers the<Progress>chassis component (paired with `progressIndicatorVari… -
progress.variants —
progressVariantsis the cva c… -
progress.variants —
progressVariantsis the cva config that powers the<Progress>chassis component (paired with `progressIndicatorVari… -
progress.variants —
progressVariantsis the cva c… -
progress.variants —
progressVariantsis the cva config that powers the<Progress>chassis component (paired with `progressIndicatorVari… -
progress.variants —
progressVariantsis the cva config that powers the<Progress>chassis component (paired with `progressIndicatorVari…
Purpose
<Progress> is the chassis progress bar built on @radix-ui/react-progress. It supports both indeterminate (Radix's loading-state animation when value === undefined) and determinate (value is 0..max, default max=100) modes. The chassis layers a size axis on top — sm (4px), default (8px), lg (12px) — while leaving width consumer-driven via className (typically w-full inside a card or form row).
The accessible name comes from the consumer-supplied aria-label (typed as TranslationKey); when absent, the chassis falls back to the bundled react-ui.progress.fallback translation key so screen-readers always announce something meaningful. This avoids the common bug where developers ship a progress bar with no accessible name and screen-readers read out the percentage without any context.
Features
- Indeterminate mode when
value === undefined(Radix runs its loading animation). - Determinate mode when
valueis a number0..max. - Three sizes via the
sizeaxis (sm/default/lg). aria-labeltyped asTranslationKey— falls back to bundledreact-ui.progress.fallbackwhen undefined.motion-safe:transition-transform motion-reduce:transition-noneon the indicator so reduced-motion users see instant updates.- Forwards refs to the Radix Root.
Usage: Basic Example
import { Progress } from "@suaveplan/react-ui";
export function UploadProgress({ percent }: { percent: number }) {
return <Progress value={percent} />;
}
Usage: Advanced Example
import { Progress } from "@suaveplan/react-ui";
export function MultiStageUpload({
currentStage,
totalStages,
isLoading,
}: {
currentStage: number;
totalStages: number;
isLoading: boolean;
}) {
return (
<Progress
size="lg"
value={isLoading ? undefined : (currentStage / totalStages) * 100}
aria-label="react-ui.loading"
className="w-64"
/>
);
}
API Reference
<Progress>
forwardRef<…, ProgressProps> — Radix Root wrapper that renders an inner Indicator translated based on value.
| Prop | Type | Default | Description |
|---|---|---|---|
value |
number | undefined |
undefined |
When defined, determinate mode; when undefined, indeterminate mode. |
max |
number |
100 |
Forwarded to Radix as the upper bound for value. |
size |
"sm" | "default" | "lg" |
"default" |
Bar height. |
aria-label |
TranslationKey | undefined |
react-ui.progress.fallback |
Accessible name. Falls back to bundled key. |
| Radix props | Radix-typed | — | All ProgressPrimitive.Root props (except aria-label which the chassis overrides). |
Errors
The Progress component calls useTranslation() to resolve the aria-label translation key. It MUST render inside a <TranslationProvider> / <ReactUiProvider>; otherwise useTranslation throws.
Implementation Notes
- When
value === undefinedthe chassis passesnullto Radix (matching Radix's API for indeterminate mode). Radix toggles itsdata-state="indeterminate"on the root and runs its built-in loading animation; consumers wanting a custom indeterminate animation override the indicator'stransformvia a[&>*]:arbitrary descendant. - The accessible-name fallback uses the bundled
react-ui.progress.fallbackkey which all five locales translate. This guarantees the screen-reader announcement is meaningful even when consumers forget to supply their own label. motion-safe:transition-transformonly runs when the user has not requested reduced motion. Reduced-motion users see the indicator snap to its new position instantly — this is intentional, animated progress with reduced-motion can cause vestibular discomfort.- The chassis does NOT expose a
getValueLabelprop (Radix supports it) because the chassis-suppliedaria-labelis sufficient for the common case; consumers wanting a percentage-readable label compose their own<span>{percent}%</span>next to the bar. - The chassis supports both indeterminate (loading) and determinate (
0..100) modes from a single component because Radix already handles the state-machine internally; splitting them into two components would force consumers to refactor when the loading-known transition lands.