Pular para o conteúdo

Badge

templates/components/Badge

O Badge é um rótulo compacto e inline (status, tag, contagem, categoria) de pegada mínima, com whitespace-nowrap/overflow-hidden e slots de adorno início/fim já embutidos na base. Seus enriquecedores acrescentam significado e microinteração DENTRO desse espaço minúsculo — sem alterar a pílula, a tipografia ou os variants.

Base congelada

Badge Secondary Destructive Outline

Conteúdo

Ponto de status

Bolinha colorida antes/depois do rótulo indicando…

Bolinha colorida antes/depois do rótulo indicando estado (online, ocupado, ausente, erro). Cor livre por estado, mesmo precedente do Status da Tabela; é adorno aditivo, não muda a base. posicionável

Ícone

Glifo lucide no slot que a…

Glifo lucide no slot que a base já provê (data-icon inline-start/inline-end), ex.: check para aprovado, cadeado para bloqueado, relógio para pendente. Conteúdo aditivo usando a afordância existente. posicionável

Contagem com limite

Quando o badge é um contador…

Quando o badge é um contador de notificações, formata o número e satura no máximo definido exibindo 'N+' (ex.: 99+). Só formata conteúdo; a pílula continua idêntica.

Comportamento

Removível (x)

Botão × que dispara um evento…

Botão × que dispara um evento de remoção — para chips de filtro e tags selecionadas. Não navega: emite dismiss para o app tirar o badge da lista. posicionável

Copiar ao clicar

Clicar copia o rótulo (código, SKU,…

Clicar copia o rótulo (código, SKU, ID, hash de commit) para a área de transferência com feedback rápido de 'copiado'. Comportamento sobre o span, distinto do variant link que navega.

Tooltip / dica

Como o badge trunca (whitespace-nowrap +…

Como o badge trunca (whitespace-nowrap + overflow-hidden), revela o texto completo ou um contexto extra ao passar o mouse ou focar. Conteúdo/comportamento aditivo em overlay. posicionável

Pulsar (ao vivo)

Animação sutil de pulso no ponto…

Animação sutil de pulso no ponto de status para sinalizar 'ao vivo / online / gravando'. É apenas movimento — não altera tipografia, cor da base, cantos nem espaçamento.

Acessibilidade

Contagem viva (aria-live)

Anuncia a leitores de tela quando…

Anuncia a leitores de tela quando o número do badge muda dinamicamente (novas notificações), estendendo a a11y da base para uso dinâmico sem alterar sua semântica estática.
Código gerado

Cole no Claude Code — ele acerta de primeira.

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

BASE CONGELADA (não mude por instância): Congelados: a pílula (rounded-4xl, h-5, w-fit), a tipografia (text-xs, font-medium), o espaçamento (px-2 py-0.5, gap-1), os 6 variants e suas cores (default/secondary/destructive/outline/ghost/link), a convenção dos slots de ícone (data-icon inline-start/inline-end com ajuste de padding), svg size-3, whitespace-nowrap + overflow-hidden, o anel focus-visible, o tratamento aria-invalid e a tag padrão span (ou 'a'). Nada disso muda ao ligar/desligar capacidade.

USO: <twig:Badge variant="default" />

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Ponto de status: Bolinha colorida antes/depois do rótulo indicando estado (online, ocupado, ausente, erro). Cor livre por estado, mesmo precedente do Status da Tabela; é adorno aditivo, não muda a base. [select → Sucesso (verde) / Aviso (âmbar) / Erro (vermelho) / Info (azul) / Neutro (cinza)]- Ícone: Glifo lucide no slot que a base já provê (data-icon inline-start/inline-end), ex.: check para aprovado, cadeado para bloqueado, relógio para pendente. Conteúdo aditivo usando a afordância existente. [select → check (aprovado) / circle-alert (erro) / clock (pendente) / lock (bloqueado) / sparkles (novo)]- Removível (x): Botão × que dispara um evento de remoção — para chips de filtro e tags selecionadas. Não navega: emite dismiss para o app tirar o badge da lista. [toggle]- Contagem com limite: Quando o badge é um contador de notificações, formata o número e satura no máximo definido exibindo 'N+' (ex.: 99+). Só formata conteúdo; a pílula continua idêntica. [number]- Copiar ao clicar: Clicar copia o rótulo (código, SKU, ID, hash de commit) para a área de transferência com feedback rápido de 'copiado'. Comportamento sobre o span, distinto do variant link que navega. [toggle]- Tooltip / dica: Como o badge trunca (whitespace-nowrap + overflow-hidden), revela o texto completo ou um contexto extra ao passar o mouse ou focar. Conteúdo/comportamento aditivo em overlay. [text]- Pulsar (ao vivo): Animação sutil de pulso no ponto de status para sinalizar 'ao vivo / online / gravando'. É apenas movimento — não altera tipografia, cor da base, cantos nem espaçamento. [toggle]- Contagem viva (aria-live): Anuncia a leitores de tela quando o número do badge muda dinamicamente (novas notificações), estendendo a a11y da base para uso dinâmico sem alterar sua semântica estática. [select → Educado (polite) / Assertivo (assertive) / Desligado]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): 5, gap-1), os 6 variants e suas cores (default/secondary/destructive/outline/ghost/link), a convenção dos slots de ícone (data-icon inline-start/inline-end com ajuste de padding), svg size-3, whitespace-nowrap + overflow-hidden, o anel focus-visible, o tratamento aria-invalid e a tag padrão span (ou 'a')

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

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

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "badge",
    "component": "Badge",
    "eixo": "ui",
    "particularidade": "O Badge é um rótulo compacto e inline (status, tag, contagem, categoria) de pegada mínima, com whitespace-nowrap/overflow-hidden e slots de adorno início/fim já embutidos na base. Seus enriquecedores acrescentam significado e microinteração DENTRO desse espaço minúsculo — sem alterar a pílula, a tipografia ou os variants.",
    "base_congelada": "Congelados: a pílula (rounded-4xl, h-5, w-fit), a tipografia (text-xs, font-medium), o espaçamento (px-2 py-0.5, gap-1), os 6 variants e suas cores (default/secondary/destructive/outline/ghost/link), a convenção dos slots de ícone (data-icon inline-start/inline-end com ajuste de padding), svg size-3, whitespace-nowrap + overflow-hidden, o anel focus-visible, o tratamento aria-invalid e a tag padrão span (ou 'a'). Nada disso muda ao ligar/desligar capacidade.",
    "props": [
        {
            "name": "variant",
            "type": "'default'|'secondary'|'destructive'|'outline'|'ghost'|'link'",
            "default": "default",
            "description": "The visual style variant. Defaults to `default` #}"
        },
        {
            "name": "as",
            "type": "'span'",
            "default": "span",
            "description": "The HTML tag to render. Defaults to `span` #}"
        }
    ],
    "capacidades": [
        {
            "id": "ponto-de-status",
            "nome": "Ponto de status",
            "descricao": "Bolinha colorida antes/depois do rótulo indicando estado (online, ocupado, ausente, erro). Cor livre por estado, mesmo precedente do Status da Tabela; é adorno aditivo, não muda a base.",
            "controle": "select",
            "opcoes": [
                "Sucesso (verde)",
                "Aviso (âmbar)",
                "Erro (vermelho)",
                "Info (azul)",
                "Neutro (cinza)"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "cone",
            "nome": "Ícone",
            "descricao": "Glifo lucide no slot que a base já provê (data-icon inline-start/inline-end), ex.: check para aprovado, cadeado para bloqueado, relógio para pendente. Conteúdo aditivo usando a afordância existente.",
            "controle": "select",
            "opcoes": [
                "check (aprovado)",
                "circle-alert (erro)",
                "clock (pendente)",
                "lock (bloqueado)",
                "sparkles (novo)"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "remov-vel-x",
            "nome": "Removível (x)",
            "descricao": "Botão × que dispara um evento de remoção — para chips de filtro e tags selecionadas. Não navega: emite dismiss para o app tirar o badge da lista.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "contagem-com-limite",
            "nome": "Contagem com limite",
            "descricao": "Quando o badge é um contador de notificações, formata o número e satura no máximo definido exibindo 'N+' (ex.: 99+). Só formata conteúdo; a pílula continua idêntica.",
            "controle": "number",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (number). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "copiar-ao-clicar",
            "nome": "Copiar ao clicar",
            "descricao": "Clicar copia o rótulo (código, SKU, ID, hash de commit) para a área de transferência com feedback rápido de 'copiado'. Comportamento sobre o span, distinto do variant link que navega.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "tooltip-dica",
            "nome": "Tooltip / dica",
            "descricao": "Como o badge trunca (whitespace-nowrap + overflow-hidden), revela o texto completo ou um contexto extra ao passar o mouse ou focar. Conteúdo/comportamento aditivo em overlay.",
            "controle": "text",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (text). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "pulsar-ao-vivo",
            "nome": "Pulsar (ao vivo)",
            "descricao": "Animação sutil de pulso no ponto de status para sinalizar 'ao vivo / online / gravando'. É apenas movimento — não altera tipografia, cor da base, cantos nem espaçamento.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "contagem-viva-aria-live",
            "nome": "Contagem viva (aria-live)",
            "descricao": "Anuncia a leitores de tela quando o número do badge muda dinamicamente (novas notificações), estendendo a a11y da base para uso dinâmico sem alterar sua semântica estática.",
            "controle": "select",
            "opcoes": [
                "Educado (polite)",
                "Assertivo (assertive)",
                "Desligado"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/badge; comportamento via controller Stimulus. Não altera a base."
        }
    ],
    "snippet_uso": "<twig:Badge variant=\"default\" />",
    "exemplo_demo": "<div class=\"flex w-full flex-wrap justify-center gap-2\">\n    <twig:Badge>Badge</twig:Badge>\n    <twig:Badge variant=\"secondary\">Secondary</twig:Badge>\n    <twig:Badge variant=\"destructive\">Destructive</twig:Badge>\n    <twig:Badge variant=\"outline\">Outline</twig:Badge>\n</div>",
    "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": "5, gap-1), os 6 variants e suas cores (default/secondary/destructive/outline/ghost/link), a convenção dos slots de ícone (data-icon inline-start/inline-end com ajuste de padding), svg size-3, whitespace-nowrap + overflow-hidden, o anel focus-visible, o tratamento aria-invalid e a tag padrão span (ou 'a')",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "badge"
        }
    }
}