Pular para o conteúdo

Item

templates/components/Item

Diferente do Card (peça isolada), o Item é uma LINHA de lista composável — Media + Content(Título/Descrição) + Actions — feita para se repetir dentro de um Item:Group (role="list") e ser interagida linha a linha (notificações, ajustes, contatos, itens de estoque de EPI). Os enriquecedores giram em torno dessa natureza de linha-em-lista: selecionar, reordenar, expandir, agir por linha e navegar pelo grupo.

Base congelada

Basic Item

A simple item with title and description.

Your profile has been verified.

Conteúdo

Indicador de não-lido / novo

Marca a linha como não-lida ou…

Marca a linha como não-lida ou nova com um marcador aditivo (ponto ou contagem), típico de listas de notificações. posicionável

Comportamento

Selecionável na linha

Transforma a linha em opção selecionável,…

Transforma a linha em opção selecionável, inserindo um controle de seleção sem mexer nos slots de conteúdo. posicionável

Selecionar tudo + contagem (grupo)

No nível do Item:Group, adiciona um…

No nível do Item:Group, adiciona um controle 'selecionar tudo' e o texto 'N de M selecionados', em sincronia com a seleção por linha. posicionável

Arrastar para reordenar

Adiciona uma alça de arraste (grip)…

Adiciona uma alça de arraste (grip) e o comportamento de reordenar as linhas dentro do Item:Group, persistindo a nova ordem. posicionável

Expansível (dobrar detalhe)

Torna a linha um disclosure: um…

Torna a linha um disclosure: um chevron abre/fecha uma região extra de detalhe abaixo do conteúdo, com aria-expanded. posicionável

Ações rápidas na linha

Escolhe quais ações aparecem no slot…

Escolhe quais ações aparecem no slot Actions (reveladas ao passar o mouse no desktop / deslizar no toque), sem poluir a linha em repouso.

Navegação por teclado no grupo

Ativa roving tabindex no Item:Group: setas…

Ativa roving tabindex no Item:Group: setas ↑/↓ movem o foco entre linhas, Home/End vão ao início/fim — melhoria de a11y sem tocar no visual.

Estado de carregamento (skeleton)

Mostra placeholders shimmer no lugar de…

Mostra placeholders shimmer no lugar de Media/Título/Descrição enquanto a linha carrega dados de forma assíncrona; estado funcional, como o loading do Button.
Código gerado

Cole no Claude Code — ele acerta de primeira.

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

BASE CONGELADA (não mude por instância): Congelado: o layout de linha flex (Media | Content | Actions, com Header/Footer em basis-full), os variants (default/outline/muted e suas bordas), os sizes (default/sm/xs com seus gaps e paddings), os cantos rounded-lg (e rounded-sm da Media imagem), a tipografia text-sm da linha, o Título font-medium line-clamp-1, a Descrição text-muted-foreground line-clamp-2, as cores/tokens (border-border, muted-foreground, hover:bg-muted no link), a transição de cor, o foco visível (focus-visible ring), o role="list" do Group, a semântica do Separator e o passthrough de {{ attributes }} e slots. Nenhuma capacidade altera fonte, cor, cantos ou espaçamento da base.

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

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Selecionável na linha: Transforma a linha em opção selecionável, inserindo um controle de seleção sem mexer nos slots de conteúdo. [select → Checkbox (seleção múltipla) / Radio (seleção única) / Nenhum]- Selecionar tudo + contagem (grupo): No nível do Item:Group, adiciona um controle 'selecionar tudo' e o texto 'N de M selecionados', em sincronia com a seleção por linha. [toggle]- Arrastar para reordenar: Adiciona uma alça de arraste (grip) e o comportamento de reordenar as linhas dentro do Item:Group, persistindo a nova ordem. [toggle]- Expansível (dobrar detalhe): Torna a linha um disclosure: um chevron abre/fecha uma região extra de detalhe abaixo do conteúdo, com aria-expanded. [toggle]- Ações rápidas na linha: Escolhe quais ações aparecem no slot Actions (reveladas ao passar o mouse no desktop / deslizar no toque), sem poluir a linha em repouso. [multi → Ver / Editar / Excluir / Arquivar / Fixar / Menu …]- Indicador de não-lido / novo: Marca a linha como não-lida ou nova com um marcador aditivo (ponto ou contagem), típico de listas de notificações. [select → Ponto / Contagem numérica / Nenhum]- Navegação por teclado no grupo: Ativa roving tabindex no Item:Group: setas ↑/↓ movem o foco entre linhas, Home/End vão ao início/fim — melhoria de a11y sem tocar no visual. [toggle]- Estado de carregamento (skeleton): Mostra placeholders shimmer no lugar de Media/Título/Descrição enquanto a linha carrega dados de forma assíncrona; estado funcional, como o loading do Button. [toggle]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): Congelado: o layout de linha flex (Media | Content | Actions, com Header/Footer em basis-full), os variants (default/outline/muted e suas bordas), os sizes (default/sm/xs com seus gaps e paddings), os cantos rounded-lg (e rounded-sm da Media imagem), a tipografia text-sm da linha, o Título font-medium line-clamp-1, a Descrição text-muted-foreground line-clamp-2, as cores/tokens (border-border, muted-foreground, hover:bg-muted no link), a transição de cor, o foco visível (focus-visible ring), o role="list" do Group, a semântica do Separator e o passthrough de {{ attributes }} e slots

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

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

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "item",
    "component": "Item",
    "eixo": "ui",
    "particularidade": "Diferente do Card (peça isolada), o Item é uma LINHA de lista composável — Media + Content(Título/Descrição) + Actions — feita para se repetir dentro de um Item:Group (role=\"list\") e ser interagida linha a linha (notificações, ajustes, contatos, itens de estoque de EPI). Os enriquecedores giram em torno dessa natureza de linha-em-lista: selecionar, reordenar, expandir, agir por linha e navegar pelo grupo.",
    "base_congelada": "Congelado: o layout de linha flex (Media | Content | Actions, com Header/Footer em basis-full), os variants (default/outline/muted e suas bordas), os sizes (default/sm/xs com seus gaps e paddings), os cantos rounded-lg (e rounded-sm da Media imagem), a tipografia text-sm da linha, o Título font-medium line-clamp-1, a Descrição text-muted-foreground line-clamp-2, as cores/tokens (border-border, muted-foreground, hover:bg-muted no link), a transição de cor, o foco visível (focus-visible ring), o role=\"list\" do Group, a semântica do Separator e o passthrough de {{ attributes }} e slots. Nenhuma capacidade altera fonte, cor, cantos ou espaçamento da base.",
    "props": [
        {
            "name": "variant",
            "type": "'default'|'outline'|'muted'",
            "default": "default",
            "description": "The visual style variant. Defaults to `default` #}"
        },
        {
            "name": "size",
            "type": "'default'|'sm'|'xs'",
            "default": "default",
            "description": "The item size. Defaults to `default` #}"
        },
        {
            "name": "as",
            "type": "'div'",
            "default": "div",
            "description": "The HTML tag to render. Defaults to `div` #}"
        }
    ],
    "capacidades": [
        {
            "id": "selecion-vel-na-linha",
            "nome": "Selecionável na linha",
            "descricao": "Transforma a linha em opção selecionável, inserindo um controle de seleção sem mexer nos slots de conteúdo.",
            "controle": "select",
            "opcoes": [
                "Checkbox (seleção múltipla)",
                "Radio (seleção única)",
                "Nenhum"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "selecionar-tudo-contagem-grupo",
            "nome": "Selecionar tudo + contagem (grupo)",
            "descricao": "No nível do Item:Group, adiciona um controle 'selecionar tudo' e o texto 'N de M selecionados', em sincronia com a seleção por linha.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "arrastar-para-reordenar",
            "nome": "Arrastar para reordenar",
            "descricao": "Adiciona uma alça de arraste (grip) e o comportamento de reordenar as linhas dentro do Item:Group, persistindo a nova ordem.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "expans-vel-dobrar-detalhe",
            "nome": "Expansível (dobrar detalhe)",
            "descricao": "Torna a linha um disclosure: um chevron abre/fecha uma região extra de detalhe abaixo do conteúdo, com aria-expanded.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "a-es-r-pidas-na-linha",
            "nome": "Ações rápidas na linha",
            "descricao": "Escolhe quais ações aparecem no slot Actions (reveladas ao passar o mouse no desktop / deslizar no toque), sem poluir a linha em repouso.",
            "controle": "multi",
            "opcoes": [
                "Ver",
                "Editar",
                "Excluir",
                "Arquivar",
                "Fixar",
                "Menu …"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (multi). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "indicador-de-n-o-lido-novo",
            "nome": "Indicador de não-lido / novo",
            "descricao": "Marca a linha como não-lida ou nova com um marcador aditivo (ponto ou contagem), típico de listas de notificações.",
            "controle": "select",
            "opcoes": [
                "Ponto",
                "Contagem numérica",
                "Nenhum"
            ],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "navega-o-por-teclado-no-grupo",
            "nome": "Navegação por teclado no grupo",
            "descricao": "Ativa roving tabindex no Item:Group: setas ↑/↓ movem o foco entre linhas, Home/End vão ao início/fim — melhoria de a11y sem tocar no visual.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "estado-de-carregamento-skeleton",
            "nome": "Estado de carregamento (skeleton)",
            "descricao": "Mostra placeholders shimmer no lugar de Media/Título/Descrição enquanto a linha carrega dados de forma assíncrona; estado funcional, como o loading do Button.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/item; comportamento via controller Stimulus. Não altera a base."
        }
    ],
    "snippet_uso": "<twig:Item variant=\"default\" />",
    "exemplo_demo": "<div class=\"flex w-full max-w-md flex-col gap-6\">\n    <twig:Item variant=\"outline\">\n        <twig:Item:Content>\n            <twig:Item:Title>Basic Item</twig:Item:Title>\n            <twig:Item:Description>\n                A simple item with title and description.\n            </twig:Item:Description>\n        </twig:Item:Content>\n        <twig:Item:Actions>\n            <twig:Button variant=\"outline\" size=\"sm\">\n                Action\n            </twig:Button>\n        </twig:Item:Actions>\n    </twig:Item>\n    <twig:Item variant=\"outline\" size=\"sm\" as=\"a\" href=\"#\">\n        <twig:Item:Media>\n            <twig:ux:icon name=\"lucide:badge-check\" class=\"size-5\" />\n        </twig:Item:Media>\n        <twig:Item:Content>\n            <twig:Item:Title>Your profile has been verified.</twig:Item:Title>\n        </twig:Item:Content>\n        <twig:Item:Actions>\n            <twig:ux:icon name=\"lucide:chevron-right\" class=\"size-4\" />\n        </twig:Item:Actions>\n    </twig:Item>\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": "Congelado: o layout de linha flex (Media | Content | Actions, com Header/Footer em basis-full), os variants (default/outline/muted e suas bordas), os sizes (default/sm/xs com seus gaps e paddings), os cantos rounded-lg (e rounded-sm da Media imagem), a tipografia text-sm da linha, o Título font-medium line-clamp-1, a Descrição text-muted-foreground line-clamp-2, as cores/tokens (border-border, muted-foreground, hover:bg-muted no link), a transição de cor, o foco visível (focus-visible ring), o role=\"list\" do Group, a semântica do Separator e o passthrough de {{ attributes }} e slots",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "item"
        }
    }
}