Progress
Indicador determinado de progresso (0–100) — uploads, multi-step, batch jobs.
Overview
Progress é uma barra determinada — você sabe a percentagem.
Use em uploads, multi-step forms, jobs que reportam progresso real.
Quando a duração é desconhecida, use Skeleton ou
spinner em vez disso.
A regra firme: nunca renderize a barra silenciosa. Sempre pareie com um valor numérico ou label de contexto — barras sem número confundem sobre o estado real ("É 60%? 70%?").
Anatomy
<Progress value={0..100}>
├─ [data-slot="progress"] ← track (h-2, bg-primary/20)
└─ <Indicator /> ← preenchimento (transform translateX)
</Progress>Usage
import { Progress } from "@kalvner/kds/feedback/progress";
export function Upload({ pct }: { pct: number }) {
return <Progress value={pct} aria-label={`${pct} por cento`} />;
}Props
| Prop | Tipo | Default | Descrição |
|---|---|---|---|
value | number | null | 0 | 0..100. null reservado para indeterminado. |
max | number | 100 | Valor máximo. |
aria-label | string | — | Obrigatório se não houver label visível associado. |
className | string | — | Override no track (h, w, bg). |
Subcomponents
Progress é monolítico — exporta apenas o root. O indicator é
interno (data-slot="progress-indicator") e estilizado via
descendentes do track.
Variants
Não há variantes embutidas. Para tamanhos custom, ajuste className:
<Progress value={50} className="h-1" /> // mais fino
<Progress value={50} className="h-3" /> // mais grossoPara cor de status (sucesso/aviso/erro), aplique no descendente:
<Progress
value={100}
className="bg-green-500/20 [&>[data-slot=progress-indicator]]:bg-green-500"
/>States
Composition
Padrão clássico de upload — label + porcentagem + barra:
<div className="space-y-2">
<div className="flex items-baseline justify-between">
<Label>Enviando arquivo</Label>
<span className="tabular-nums text-muted-foreground">{pct}%</span>
</div>
<Progress value={pct} aria-label={`${pct} por cento`} />
</div>Em multi-step forms, mostre current/total em vez de porcentagem:
<div className="space-y-2">
<span className="text-sm">Passo 2 de 4</span>
<Progress value={(2 / 4) * 100} aria-label="Passo 2 de 4" />
</div>When to use
- Uploads / downloads em andamento.
- Multi-step forms (passo N de M).
- Batch jobs com porcentagem real.
- Onboarding com checklist progressivo.
When not to use
- Operações de duração desconhecida — use Skeleton ou spinner.
- "Loading..." curto (menos de 1s) — não vale a pena mostrar.
- Dados em tempo real que sobem e descem (CPU, memória) — use um gráfico Sequential da Chart layer.
Best practices
- Sempre pareie com número visível ou label dinâmico.
- Use
tabular-numsno número para evitar saltos de largura. - Em uploads que podem cancelar, ofereça botão
Cancelao lado da barra. - Para 100%, troque a label para uma confirmação ("Concluído") e mantenha a barra cheia 800ms antes de remover — evita flash.
Accessibility
| Concern | Comportamento |
|---|---|
| Roles | Radix expõe role="progressbar" com aria-valuenow, aria-valuemin=0, aria-valuemax=100. |
| Label | aria-label ou aria-labelledby é obrigatório. |
| Live region | Para feedback de operação, embrulhe num aria-live="polite" no container. |
| Reduced motion | A transition-all no indicator respeita prefers-reduced-motion. |