Pular para o conteúdo

Avatar

templates/components/Avatar

O Avatar responde "quem é" no menor espaço possível: uma imagem circular que degrada graciosamente para iniciais (Fallback) e, na falha, para um ícone. Traz um selo no canto (Badge) para status/notificação e empilha sobrepostos em grupo (Group + "+N") — sempre representando identidade, nunca conteúdo genérico.

Base congelada

CN ER
CN LR ER
+3

Conteúdo

Indicador de presença

Mapeia um estado semântico (online/ausente/ocupado/offline/invisível) no…

Mapeia um estado semântico (online/ausente/ocupado/offline/invisível) no Avatar:Badge do canto — reusa o selo congelado, muda só a cor semântica do estado (precedente: Status da Tabela). posicionável

Iniciais automáticas do nome

Deriva as iniciais a partir do…

Deriva as iniciais a partir do nome completo (ex.: 'Bruno Peters' → 'BP'), 1-2 letras em caixa alta, e preenche o Avatar:Fallback — sem digitar 'BP' à mão, sem tocar no visual do fallback.

Cascata de fallback (imagem → iniciais → ícone)

Trata o onerror que a base…

Trata o onerror que a base do Image não cobre: se a URL quebra (404/offline), cai para iniciais e, sem iniciais, para um ícone genérico de usuário — sem imagem quebrada.

Contador de notificações

Exibe um número (mensagens/pendências) reusando o…

Exibe um número (mensagens/pendências) reusando o Avatar:Badge como selo numérico, distinto do status de presença; conteúdo aditivo dentro do selo congelado. posicionável

Empilhar com limite (+N automático)

No Avatar:Group, define quantos avatares aparecem;…

No Avatar:Group, define quantos avatares aparecem; o excedente é resumido automaticamente no Avatar:GroupCount ('+N') — truncamento comportamental reusando os slots do grupo.

Ordem de sobreposição do grupo

Escolhe qual avatar fica por cima…

Escolhe qual avatar fica por cima na pilha sobreposta (primeiro na frente ou último na frente) — apenas z-index, sem mexer no -space-x-2 nem no anel congelados.

Comportamento

Tooltip de identidade

Ao passar o mouse/foco, revela nome…

Ao passar o mouse/foco, revela nome e cargo do avatar reusando o componente Tooltip — desambigua rostos em grupos sem rótulo permanente ocupando espaço. posicionável

Perfil clicável

Envolve o avatar num link/ação para…

Envolve o avatar num link/ação para o perfil, adicionando papel interativo, foco e teclado (a11y) — sem alterar o anel de foco, que já é convenção da base.
Código gerado

Cole no Claude Code — ele acerta de primeira.

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

BASE CONGELADA (não mude por instância): Forma circular (rounded-full), tamanhos sm/default/lg (size-6/8/10 via data-size), o anel/borda sutil (after:border-border; ring-2 ring-background no grupo), o Fallback em bg-muted/text-muted-foreground text-sm, o Badge fixado no canto com ring-2, a sobreposição -space-x-2 do Group, o aspect-square/object-cover da imagem e a semântica/a11y (alt obrigatório, select-none). Ligar/desligar qualquer capacidade não altera nada disso — só comportamento e conteúdo aditivo dentro dos slots já existentes.

USO: <twig:Avatar size="default" />

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Indicador de presença: Mapeia um estado semântico (online/ausente/ocupado/offline/invisível) no Avatar:Badge do canto — reusa o selo congelado, muda só a cor semântica do estado (precedente: Status da Tabela). [select → Online / Ausente / Ocupado / Offline / Invisível]- Iniciais automáticas do nome: Deriva as iniciais a partir do nome completo (ex.: 'Bruno Peters' → 'BP'), 1-2 letras em caixa alta, e preenche o Avatar:Fallback — sem digitar 'BP' à mão, sem tocar no visual do fallback. [text]- Cascata de fallback (imagem → iniciais → ícone): Trata o onerror que a base do Image não cobre: se a URL quebra (404/offline), cai para iniciais e, sem iniciais, para um ícone genérico de usuário — sem imagem quebrada. [select → Iniciais / Ícone de usuário / Iniciais e depois ícone]- Contador de notificações: Exibe um número (mensagens/pendências) reusando o Avatar:Badge como selo numérico, distinto do status de presença; conteúdo aditivo dentro do selo congelado. [number]- Tooltip de identidade: Ao passar o mouse/foco, revela nome e cargo do avatar reusando o componente Tooltip — desambigua rostos em grupos sem rótulo permanente ocupando espaço. [toggle]- Perfil clicável: Envolve o avatar num link/ação para o perfil, adicionando papel interativo, foco e teclado (a11y) — sem alterar o anel de foco, que já é convenção da base. [text]- Empilhar com limite (+N automático): No Avatar:Group, define quantos avatares aparecem; o excedente é resumido automaticamente no Avatar:GroupCount ('+N') — truncamento comportamental reusando os slots do grupo. [number]- Ordem de sobreposição do grupo: Escolhe qual avatar fica por cima na pilha sobreposta (primeiro na frente ou último na frente) — apenas z-index, sem mexer no -space-x-2 nem no anel congelados. [select → Primeiro na frente / Último na frente]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): ring-2 ring-background no grupo), o Fallback em bg-muted/text-muted-foreground text-sm, o Badge fixado no canto com ring-2, a sobreposição -space-x-2 do Group, o aspect-square/object-cover da imagem e a semântica/a11y (alt obrigatório, select-none)

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

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

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "avatar",
    "component": "Avatar",
    "eixo": "ui",
    "particularidade": "O Avatar responde \"quem é\" no menor espaço possível: uma imagem circular que degrada graciosamente para iniciais (Fallback) e, na falha, para um ícone. Traz um selo no canto (Badge) para status/notificação e empilha sobrepostos em grupo (Group + \"+N\") — sempre representando identidade, nunca conteúdo genérico.",
    "base_congelada": "Forma circular (rounded-full), tamanhos sm/default/lg (size-6/8/10 via data-size), o anel/borda sutil (after:border-border; ring-2 ring-background no grupo), o Fallback em bg-muted/text-muted-foreground text-sm, o Badge fixado no canto com ring-2, a sobreposição -space-x-2 do Group, o aspect-square/object-cover da imagem e a semântica/a11y (alt obrigatório, select-none). Ligar/desligar qualquer capacidade não altera nada disso — só comportamento e conteúdo aditivo dentro dos slots já existentes.",
    "props": [
        {
            "name": "size",
            "type": "'default'|'sm'|'lg'",
            "default": "default",
            "description": "The avatar size. Defaults to `default` #}"
        }
    ],
    "capacidades": [
        {
            "id": "indicador-de-presen-a",
            "nome": "Indicador de presença",
            "descricao": "Mapeia um estado semântico (online/ausente/ocupado/offline/invisível) no Avatar:Badge do canto — reusa o selo congelado, muda só a cor semântica do estado (precedente: Status da Tabela).",
            "controle": "select",
            "opcoes": [
                "Online",
                "Ausente",
                "Ocupado",
                "Offline",
                "Invisível"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "iniciais-autom-ticas-do-nome",
            "nome": "Iniciais automáticas do nome",
            "descricao": "Deriva as iniciais a partir do nome completo (ex.: 'Bruno Peters' → 'BP'), 1-2 letras em caixa alta, e preenche o Avatar:Fallback — sem digitar 'BP' à mão, sem tocar no visual do fallback.",
            "controle": "text",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (text). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "cascata-de-fallback-imagem-iniciais-cone",
            "nome": "Cascata de fallback (imagem → iniciais → ícone)",
            "descricao": "Trata o onerror que a base do Image não cobre: se a URL quebra (404/offline), cai para iniciais e, sem iniciais, para um ícone genérico de usuário — sem imagem quebrada.",
            "controle": "select",
            "opcoes": [
                "Iniciais",
                "Ícone de usuário",
                "Iniciais e depois ícone"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "contador-de-notifica-es",
            "nome": "Contador de notificações",
            "descricao": "Exibe um número (mensagens/pendências) reusando o Avatar:Badge como selo numérico, distinto do status de presença; conteúdo aditivo dentro do selo congelado.",
            "controle": "number",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (number). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "tooltip-de-identidade",
            "nome": "Tooltip de identidade",
            "descricao": "Ao passar o mouse/foco, revela nome e cargo do avatar reusando o componente Tooltip — desambigua rostos em grupos sem rótulo permanente ocupando espaço.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "perfil-clic-vel",
            "nome": "Perfil clicável",
            "descricao": "Envolve o avatar num link/ação para o perfil, adicionando papel interativo, foco e teclado (a11y) — sem alterar o anel de foco, que já é convenção da base.",
            "controle": "text",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (text). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "empilhar-com-limite-n-autom-tico",
            "nome": "Empilhar com limite (+N automático)",
            "descricao": "No Avatar:Group, define quantos avatares aparecem; o excedente é resumido automaticamente no Avatar:GroupCount ('+N') — truncamento comportamental reusando os slots do grupo.",
            "controle": "number",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (number). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "ordem-de-sobreposi-o-do-grupo",
            "nome": "Ordem de sobreposição do grupo",
            "descricao": "Escolhe qual avatar fica por cima na pilha sobreposta (primeiro na frente ou último na frente) — apenas z-index, sem mexer no -space-x-2 nem no anel congelados.",
            "controle": "select",
            "opcoes": [
                "Primeiro na frente",
                "Último na frente"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/avatar; comportamento via controller Stimulus. Não altera a base."
        }
    ],
    "snippet_uso": "<twig:Avatar size=\"default\" />",
    "exemplo_demo": "<div class=\"flex flex-row flex-wrap items-center gap-6 md:gap-12\">\n    <twig:Avatar>\n        <twig:Avatar:Image\n            src=\"https://github.com/shadcn.png\"\n            alt=\"@shadcn\"\n            class=\"grayscale\"\n        />\n        <twig:Avatar:Fallback>CN</twig:Avatar:Fallback>\n    </twig:Avatar>\n    <twig:Avatar>\n        <twig:Avatar:Image src=\"https://github.com/evilrabbit.png\" alt=\"@evilrabbit\" />\n        <twig:Avatar:Fallback>ER</twig:Avatar:Fallback>\n        <twig:Avatar:Badge class=\"bg-green-600 dark:bg-green-800\" />\n    </twig:Avatar>\n    <twig:Avatar:Group class=\"grayscale\">\n        <twig:Avatar>\n            <twig:Avatar:Image src=\"https://github.com/shadcn.png\" alt=\"@shadcn\" />\n            <twig:Avatar:Fallback>CN</twig:Avatar:Fallback>\n        </twig:Avatar>\n        <twig:Avatar>\n            <twig:Avatar:Image src=\"https://github.com/maxleiter.png\" alt=\"@maxleiter\" />\n            <twig:Avatar:Fallback>LR</twig:Avatar:Fallback>\n        </twig:Avatar>\n        <twig:Avatar>\n            <twig:Avatar:Image src=\"https://github.com/evilrabbit.png\" alt=\"@evilrabbit\" />\n            <twig:Avatar:Fallback>ER</twig:Avatar:Fallback>\n        </twig:Avatar>\n        <twig:Avatar:GroupCount>+3</twig:Avatar:GroupCount>\n    </twig:Avatar:Group>\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": "ring-2 ring-background no grupo), o Fallback em bg-muted/text-muted-foreground text-sm, o Badge fixado no canto com ring-2, a sobreposição -space-x-2 do Group, o aspect-square/object-cover da imagem e a semântica/a11y (alt obrigatório, select-none)",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "avatar"
        }
    }
}