Pular para o conteúdo

Progress

templates/components/Progress

É o único componente cujo significado é um número em movimento (0–100) representando o avanço de uma operação temporal/assíncrona — upload, processamento, quota, arrecadação, força de senha. Por isso os enriquecedores giram em torno de LER, interpretar e reagir a esse número e ao ciclo de vida da operação — nunca de reestilizar a barra.

Base congelada

Conteúdo

Rótulo de valor

Exibe a leitura numérica do progresso…

Exibe a leitura numérica do progresso como texto ao lado da barra, sem tocar na barra. posicionável

Marcador de meta

Fixa um traço de referência num…

Fixa um traço de referência num alvo (ex.: 80%) para usar a barra como medidor de objetivo — orçamento, arrecadação, KPI.

Buffer (progresso secundário)

Camada secundária no mesmo token primary…

Camada secundária no mesmo token primary com menor ênfase, para dois níveis: 'carregado vs. processado' ou buffer de streaming.

Selo de conclusão

Ao chegar a 100%, acrescenta uma…

Ao chegar a 100%, acrescenta uma marca de conclusão (ícone check e/ou texto 'Concluído') — conteúdo aditivo do ciclo de vida. posicionável

Tempo restante (ETA)

Deriva do ritmo de avanço uma…

Deriva do ritmo de avanço uma estimativa de tempo ('~2 min restantes') exibida como texto — comportamental e aditivo. posicionável

Legenda / rótulo descritivo

Texto livre descrevendo a operação em…

Texto livre descrevendo a operação em curso ('Enviando relatório…', '3 de 5 etapas'), acima ou abaixo da barra. posicionável

Cor por faixa (limiar semântico) ⚠️

Troca o preenchimento por tokens semânticos…

Troca o preenchimento por tokens semânticos de estado conforme a faixa de valor (risco/atenção/sucesso) — útil em força de senha/quota. Honestamente TOCA na cor: a paleta de estado é decisão de base (definida uma vez em app.css); só o gatilho por faixa seria o opt-in.

Comportamento

Indeterminado

Quando o valor é desconhecido, o…

Quando o valor é desconhecido, o indicador vira uma animação em laço; a a11y remove aria-valuenow.
Código gerado

Cole no Claude Code — ele acerta de primeira.

Progress (UI) — Design System (Symfony UX Toolkit / shadcn)

BASE CONGELADA (não mude por instância): Estrutura de dois slots congelada: track `div[role=progressbar]` + `div[data-slot=progress-indicator]`, com altura `h-1`, largura `w-full`, cantos `rounded-full`, track `bg-muted`, indicador `bg-primary`, `overflow-x-hidden` e `transition-all`. O preenchimento é sempre `translateX(-(100-value)%)`. Prop única `value` (0–100). a11y imutável: `role=progressbar`, `aria-valuemin=0`, `aria-valuemax=100`, `aria-valuenow=value`. Altura, cor primária, cantos e tipografia são intocáveis — consequência direta: "tamanho da barra" (h-1 → h-2/h-3) NÃO é enricher, é decisão de base (muda para todos em app.css). Rótulos textuais adotam a tipografia congelada do DS e ficam FORA da barra (a h-1 é fina demais para texto interno).

USO: <twig:Progress />

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Rótulo de valor: Exibe a leitura numérica do progresso como texto ao lado da barra, sem tocar na barra. [select → Porcentagem (56%) / Fração (56/100) / Medida (5,6/10 MB) / Sem rótulo]- Indeterminado: Quando o valor é desconhecido, o indicador vira uma animação em laço; a a11y remove aria-valuenow. [toggle]- Marcador de meta: Fixa um traço de referência num alvo (ex.: 80%) para usar a barra como medidor de objetivo — orçamento, arrecadação, KPI. [number]- Buffer (progresso secundário): Camada secundária no mesmo token primary com menor ênfase, para dois níveis: 'carregado vs. processado' ou buffer de streaming. [toggle]- Selo de conclusão: Ao chegar a 100%, acrescenta uma marca de conclusão (ícone check e/ou texto 'Concluído') — conteúdo aditivo do ciclo de vida. [select → Sem selo / Ícone (check) / Texto (Concluído) / Ícone + texto]- Tempo restante (ETA): Deriva do ritmo de avanço uma estimativa de tempo ('~2 min restantes') exibida como texto — comportamental e aditivo. [toggle]- Legenda / rótulo descritivo: Texto livre descrevendo a operação em curso ('Enviando relatório…', '3 de 5 etapas'), acima ou abaixo da barra. [text]- Cor por faixa (limiar semântico): Troca o preenchimento por tokens semânticos de estado conforme a faixa de valor (risco/atenção/sucesso) — útil em força de senha/quota. Honestamente TOCA na cor: a paleta de estado é decisão de base (definida uma vez em app.css); só o gatilho por faixa seria o opt-in. [multi → Faixa de risco (baixo) / Faixa de atenção (médio) / Faixa de sucesso (alto)]  (⚠️ borderline: revisar se não é decisão de base)FAÇA:
- Use <twig:Nome> — a base é congelada, você é dono do template em templates/components/.
- Ligue apenas capacidades opt-in listadas (e_funcao=true); a aparência não muda ao ligá-las.
- Passe atributos extras (id, aria-*, name, data-*) via {{ attributes }}.
NÃO FAÇA:
- Não mude cor/fonte/cantos/espaçamento por instância — é decisão de BASE, na fonte única assets/styles/app.css.
- Não crie variante/fork para a mesma coisa — existe UMA base por componente.
- Não reimplemente o componente nem adicione toolchain Node.
TESTE ANTES DE MUDAR: "é função ou é base?" — função = capacidade opt-in; base = mude o token na fonte única (assets/styles/app.css), para todos.

A11Y (herdada da base): Estrutura de dois slots congelada: track `div[role=progressbar]` + `div[data-slot=progress-indicator]`, com altura `h-1`, largura `w-full`, cantos `rounded-full`, track `bg-muted`, indicador `bg-primary`, `overflow-x-hidden` e `transition-all`. a11y imutável: `role=progressbar`, `aria-valuemin=0`, `aria-valuemax=100`, `aria-valuenow=value`

Via MCP: tool get_component com {"id": "progress"} · list_capabilities("progress").

Spec crua: config/ds-specs/progress.json · Conectar o MCP.

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "progress",
    "component": "Progress",
    "eixo": "ui",
    "particularidade": "É o único componente cujo significado é um número em movimento (0–100) representando o avanço de uma operação temporal/assíncrona — upload, processamento, quota, arrecadação, força de senha. Por isso os enriquecedores giram em torno de LER, interpretar e reagir a esse número e ao ciclo de vida da operação — nunca de reestilizar a barra.",
    "base_congelada": "Estrutura de dois slots congelada: track `div[role=progressbar]` + `div[data-slot=progress-indicator]`, com altura `h-1`, largura `w-full`, cantos `rounded-full`, track `bg-muted`, indicador `bg-primary`, `overflow-x-hidden` e `transition-all`. O preenchimento é sempre `translateX(-(100-value)%)`. Prop única `value` (0–100). a11y imutável: `role=progressbar`, `aria-valuemin=0`, `aria-valuemax=100`, `aria-valuenow=value`. Altura, cor primária, cantos e tipografia são intocáveis — consequência direta: \"tamanho da barra\" (h-1 → h-2/h-3) NÃO é enricher, é decisão de base (muda para todos em app.css). Rótulos textuais adotam a tipografia congelada do DS e ficam FORA da barra (a h-1 é fina demais para texto interno).",
    "props": [
        {
            "name": "value",
            "type": "integer",
            "default": "0",
            "description": "The progress percentage (0-100). Defaults to `0` #}"
        }
    ],
    "capacidades": [
        {
            "id": "r-tulo-de-valor",
            "nome": "Rótulo de valor",
            "descricao": "Exibe a leitura numérica do progresso como texto ao lado da barra, sem tocar na barra.",
            "controle": "select",
            "opcoes": [
                "Porcentagem (56%)",
                "Fração (56/100)",
                "Medida (5,6/10 MB)",
                "Sem rótulo"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/progress; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "indeterminado",
            "nome": "Indeterminado",
            "descricao": "Quando o valor é desconhecido, o indicador vira uma animação em laço; a a11y remove aria-valuenow.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/progress; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "marcador-de-meta",
            "nome": "Marcador de meta",
            "descricao": "Fixa um traço de referência num alvo (ex.: 80%) para usar a barra como medidor de objetivo — orçamento, arrecadação, KPI.",
            "controle": "number",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (number). Ligue no configurador em /vitrine/ui/progress; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "buffer-progresso-secund-rio",
            "nome": "Buffer (progresso secundário)",
            "descricao": "Camada secundária no mesmo token primary com menor ênfase, para dois níveis: 'carregado vs. processado' ou buffer de streaming.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/progress; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "selo-de-conclus-o",
            "nome": "Selo de conclusão",
            "descricao": "Ao chegar a 100%, acrescenta uma marca de conclusão (ícone check e/ou texto 'Concluído') — conteúdo aditivo do ciclo de vida.",
            "controle": "select",
            "opcoes": [
                "Sem selo",
                "Ícone (check)",
                "Texto (Concluído)",
                "Ícone + texto"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/progress; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "tempo-restante-eta",
            "nome": "Tempo restante (ETA)",
            "descricao": "Deriva do ritmo de avanço uma estimativa de tempo ('~2 min restantes') exibida como texto — comportamental e aditivo.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/progress; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "legenda-r-tulo-descritivo",
            "nome": "Legenda / rótulo descritivo",
            "descricao": "Texto livre descrevendo a operação em curso ('Enviando relatório…', '3 de 5 etapas'), acima ou abaixo da barra.",
            "controle": "text",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (text). Ligue no configurador em /vitrine/ui/progress; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "cor-por-faixa-limiar-sem-ntico",
            "nome": "Cor por faixa (limiar semântico)",
            "descricao": "Troca o preenchimento por tokens semânticos de estado conforme a faixa de valor (risco/atenção/sucesso) — útil em força de senha/quota. Honestamente TOCA na cor: a paleta de estado é decisão de base (definida uma vez em app.css); só o gatilho por faixa seria o opt-in.",
            "controle": "multi",
            "opcoes": [
                "Faixa de risco (baixo)",
                "Faixa de atenção (médio)",
                "Faixa de sucesso (alto)"
            ],
            "posicionavel": false,
            "e_funcao": false,
            "como_plugar": "REPROVADO no teste 'é função ou é base' — NÃO plugar como capacidade. É decisão de BASE: mude o token na fonte única assets/styles/app.css, valendo para TODOS os componentes."
        }
    ],
    "snippet_uso": "<twig:Progress />",
    "exemplo_demo": "<twig:Progress value=\"56\" class=\"w-[60%]\" />",
    "regras": {
        "faca": [
            "Use <twig:Nome> — a base é congelada, você é dono do template em templates/components/.",
            "Ligue apenas capacidades opt-in listadas (e_funcao=true); a aparência não muda ao ligá-las.",
            "Passe atributos extras (id, aria-*, name, data-*) via {{ attributes }}."
        ],
        "nao_faca": [
            "Não mude cor/fonte/cantos/espaçamento por instância — é decisão de BASE, na fonte única assets/styles/app.css.",
            "Não crie variante/fork para a mesma coisa — existe UMA base por componente.",
            "Não reimplemente o componente nem adicione toolchain Node."
        ]
    },
    "a11y": "Estrutura de dois slots congelada: track `div[role=progressbar]` + `div[data-slot=progress-indicator]`, com altura `h-1`, largura `w-full`, cantos `rounded-full`, track `bg-muted`, indicador `bg-primary`, `overflow-x-hidden` e `transition-all`. a11y imutável: `role=progressbar`, `aria-valuemin=0`, `aria-valuemax=100`, `aria-valuenow=value`",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "progress"
        }
    }
}