Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
# Progress
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - progress.variants — `progressVariants` is the cva c…
- [progress.variants](./progress.variants.md) — `progressVariants` is the cva config that powers the `<Progress>` chassis component (paired with `progressIndicatorVari…
- progress.variants — `progressVariants` is the cva c…
- [progress.variants](./progress.variants.md) — `progressVariants` is the cva config that powers the `<Progress>` chassis component (paired with `progressIndicatorVari…
- progress.variants — `progressVariants` is the cva c…
- [progress.variants](./progress.variants.md) — `progressVariants` is the cva config that powers the `<Progress>` chassis component (paired with `progressIndicatorVari…
- progress.variants — `progressVariants` is the cva c…
- [progress.variants](./progress.variants.md) — `progressVariants` is the cva config that powers the `<Progress>` chassis component (paired with `progressIndicatorVari…
- [progress.variants](./progress.variants.md) — `progressVariants` is 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 `value` is a number `0..max`.
- Three sizes via the `size` axis (`sm` / `default` / `lg`).
- `aria-label` typed as `TranslationKey` — falls back to bundled `react-ui.progress.fallback` when undefined.
- `motion-safe:transition-transform motion-reduce:transition-none` on the indicator so reduced-motion users see instant updates.
- Forwards refs to the Radix Root.
## Usage: Basic Example
```tsx
import { Progress } from "@suaveplan/react-ui";
export function UploadProgress({ percent }: { percent: number }) {
return <Progress value={percent} />;
}
```
## Usage: Advanced Example
```tsx
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 === undefined` the chassis passes `null` to Radix (matching Radix's API for indeterminate mode). Radix toggles its `data-state="indeterminate"` on the root and runs its built-in loading animation; consumers wanting a custom indeterminate animation override the indicator's `transform` via a `[&>*]:` arbitrary descendant.
- The accessible-name fallback uses the bundled `react-ui.progress.fallback` key 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-transform` only 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 `getValueLabel` prop (Radix supports it) because the chassis-supplied `aria-label` is 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.