Pular para o conteúdo

Accordion

templates/components/Accordion

O Accordion é uma pilha de seções colapsáveis: sua particularidade é gerenciar QUAIS painéis estão revelados — abrir um ou vários, navegar por teclado e animar a expansão de cada bloco de conteúdo sob cabeçalhos clicáveis. Os enrichers giram em torno de controlar, encontrar, lembrar e anotar essas seções, sem tocar no visual congelado do disclosure.

Base congelada

We offer standard (5-7 days), express (2-3 days), and overnight shipping. Free shipping on international orders.

Conteúdo

Lembrar seções abertas

Persiste quais paineis o usuario deixou…

Persiste quais paineis o usuario deixou abertos e restaura no proximo acesso, ou permite deep-link para uma secao especifica. Comportamento puro sobre o defaultValue da base.

Carregar conteúdo sob demanda

Adia a renderizacao do conteudo de…

Adia a renderizacao do conteudo de cada painel ate a primeira abertura (lazy). Alivia paginas com muitas secoes pesadas; a base continua identica, so muda quando o HTML entra.

Contador no cabeçalho

Slot de contagem numerica (Badge congelado)…

Slot de contagem numerica (Badge congelado) por secao — ex.: no de itens/pendencias dentro do painel — exibido na linha do Trigger. Conteudo aditivo, a la badge por aba. posicionável

Ícone da seção

Slot de icone por item ao…

Slot de icone por item ao lado do rotulo do Trigger, para categorizar visualmente as secoes (financeiro, seguranca, envio...). Conteudo aditivo usando o tamanho de icone ja congelado. posicionável

Comportamento

Expandir / recolher todos

Botão de barra que abre ou…

Botão de barra que abre ou fecha todas as seções de uma vez; só faz sentido quando a base está em multiple=true. Reflete o estado atual (Expandir tudo x Recolher tudo). posicionável

Buscar e filtrar seções

Campo de busca que filtra os…

Campo de busca que filtra os itens pelo texto do cabeçalho (e opcionalmente do conteudo), ocultando os que nao casam e auto-expandindo os que casam. Ideal para FAQ longa. posicionável

Rolar até a seção ao abrir

Ao expandir um item, rola a…

Ao expandir um item, rola a pagina para trazer o cabecalho/conteudo a vista — util quando o painel aberto cresce e empurra o resto para fora da tela.

Manter ao menos um aberto

Impede recolher a ultima secao aberta…

Impede recolher a ultima secao aberta (nao-colapsavel), garantindo que sempre haja um painel visivel. Guarda de comportamento independente do multiple.
Código gerado

Cole no Claude Code — ele acerta de primeira.

Accordion (UX) — Design System (Symfony UX Toolkit / shadcn)

BASE CONGELADA (não mude por instância): Estrutura Trigger+Content e o chevron para baixo/cima que alterna sozinho à direita; a borda entre itens (not-last:border-b), cantos rounded-lg, espaçamento py-2.5, texto text-sm font-medium, a animação grid-template-rows (duration-300 ease-out) e toda a a11y: h3>button, aria-expanded/aria-controls, role=region, aria-labelledby, navegação por setas (up/down conforme orientation) e anel de foco. Os props NATIVOS multiple (um vs. vários abertos), defaultValue (quais abrem), orientation (vertical/horizontal) e o disabled/open por Item já são BASE — não contam como enrichers.

USO: <twig:Accordion />

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Expandir / recolher todos: Botão de barra que abre ou fecha todas as seções de uma vez; só faz sentido quando a base está em multiple=true. Reflete o estado atual (Expandir tudo x Recolher tudo). [toggle]- Buscar e filtrar seções: Campo de busca que filtra os itens pelo texto do cabeçalho (e opcionalmente do conteudo), ocultando os que nao casam e auto-expandindo os que casam. Ideal para FAQ longa. [toggle]- Lembrar seções abertas: Persiste quais paineis o usuario deixou abertos e restaura no proximo acesso, ou permite deep-link para uma secao especifica. Comportamento puro sobre o defaultValue da base. [select → Nao lembrar / Local (localStorage) / URL (deep-link no hash)]- Rolar até a seção ao abrir: Ao expandir um item, rola a pagina para trazer o cabecalho/conteudo a vista — util quando o painel aberto cresce e empurra o resto para fora da tela. [toggle]- Carregar conteúdo sob demanda: Adia a renderizacao do conteudo de cada painel ate a primeira abertura (lazy). Alivia paginas com muitas secoes pesadas; a base continua identica, so muda quando o HTML entra. [toggle]- Manter ao menos um aberto: Impede recolher a ultima secao aberta (nao-colapsavel), garantindo que sempre haja um painel visivel. Guarda de comportamento independente do multiple. [toggle]- Contador no cabeçalho: Slot de contagem numerica (Badge congelado) por secao — ex.: no de itens/pendencias dentro do painel — exibido na linha do Trigger. Conteudo aditivo, a la badge por aba. [toggle]- Ícone da seção: Slot de icone por item ao lado do rotulo do Trigger, para categorizar visualmente as secoes (financeiro, seguranca, envio...). Conteudo aditivo usando o tamanho de icone ja congelado. [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): 5, texto text-sm font-medium, a animação grid-template-rows (duration-300 ease-out) e toda a a11y: h3>button, aria-expanded/aria-controls, role=region, aria-labelledby, navegação por setas (up/down conforme orientation) e anel de foco

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

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

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "accordion",
    "component": "Accordion",
    "eixo": "ux",
    "particularidade": "O Accordion é uma pilha de seções colapsáveis: sua particularidade é gerenciar QUAIS painéis estão revelados — abrir um ou vários, navegar por teclado e animar a expansão de cada bloco de conteúdo sob cabeçalhos clicáveis. Os enrichers giram em torno de controlar, encontrar, lembrar e anotar essas seções, sem tocar no visual congelado do disclosure.",
    "base_congelada": "Estrutura Trigger+Content e o chevron para baixo/cima que alterna sozinho à direita; a borda entre itens (not-last:border-b), cantos rounded-lg, espaçamento py-2.5, texto text-sm font-medium, a animação grid-template-rows (duration-300 ease-out) e toda a a11y: h3>button, aria-expanded/aria-controls, role=region, aria-labelledby, navegação por setas (up/down conforme orientation) e anel de foco. Os props NATIVOS multiple (um vs. vários abertos), defaultValue (quais abrem), orientation (vertical/horizontal) e o disabled/open por Item já são BASE — não contam como enrichers.",
    "props": [
        {
            "name": "multiple",
            "type": "boolean",
            "default": "false",
            "description": "Whether multiple items can be opened at once. Defaults to `false` #}"
        },
        {
            "name": "defaultValue",
            "type": "string|array<string>|null",
            "default": "null",
            "description": "Value(s) of the item(s) to open by default #}"
        },
        {
            "name": "orientation",
            "type": "'vertical'|'horizontal'",
            "default": "vertical",
            "description": "The visual orientation, controls whether keyboard navigation uses up/down or left/right arrow keys. Defaults to `vertical` #}"
        },
        {
            "name": "id",
            "type": "string",
            "default": null,
            "description": "Unique identifier for the Accordion #}"
        }
    ],
    "capacidades": [
        {
            "id": "expandir-recolher-todos",
            "nome": "Expandir / recolher todos",
            "descricao": "Botão de barra que abre ou fecha todas as seções de uma vez; só faz sentido quando a base está em multiple=true. Reflete o estado atual (Expandir tudo x Recolher tudo).",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "buscar-e-filtrar-se-es",
            "nome": "Buscar e filtrar seções",
            "descricao": "Campo de busca que filtra os itens pelo texto do cabeçalho (e opcionalmente do conteudo), ocultando os que nao casam e auto-expandindo os que casam. Ideal para FAQ longa.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "lembrar-se-es-abertas",
            "nome": "Lembrar seções abertas",
            "descricao": "Persiste quais paineis o usuario deixou abertos e restaura no proximo acesso, ou permite deep-link para uma secao especifica. Comportamento puro sobre o defaultValue da base.",
            "controle": "select",
            "opcoes": [
                "Nao lembrar",
                "Local (localStorage)",
                "URL (deep-link no hash)"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "rolar-at-a-se-o-ao-abrir",
            "nome": "Rolar até a seção ao abrir",
            "descricao": "Ao expandir um item, rola a pagina para trazer o cabecalho/conteudo a vista — util quando o painel aberto cresce e empurra o resto para fora da tela.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "carregar-conte-do-sob-demanda",
            "nome": "Carregar conteúdo sob demanda",
            "descricao": "Adia a renderizacao do conteudo de cada painel ate a primeira abertura (lazy). Alivia paginas com muitas secoes pesadas; a base continua identica, so muda quando o HTML entra.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "manter-ao-menos-um-aberto",
            "nome": "Manter ao menos um aberto",
            "descricao": "Impede recolher a ultima secao aberta (nao-colapsavel), garantindo que sempre haja um painel visivel. Guarda de comportamento independente do multiple.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "contador-no-cabe-alho",
            "nome": "Contador no cabeçalho",
            "descricao": "Slot de contagem numerica (Badge congelado) por secao — ex.: no de itens/pendencias dentro do painel — exibido na linha do Trigger. Conteudo aditivo, a la badge por aba.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "cone-da-se-o",
            "nome": "Ícone da seção",
            "descricao": "Slot de icone por item ao lado do rotulo do Trigger, para categorizar visualmente as secoes (financeiro, seguranca, envio...). Conteudo aditivo usando o tamanho de icone ja congelado.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/accordion; comportamento via controller Stimulus. Não altera a base."
        }
    ],
    "snippet_uso": "<twig:Accordion />",
    "exemplo_demo": "<twig:Accordion id=\"accordion-demo\" defaultValue=\"{{ ['shipping'] }}\" class=\"max-w-lg\">\n    <twig:Accordion:Item value=\"shipping\">\n        <twig:Accordion:Trigger>What are your shipping options?</twig:Accordion:Trigger>\n        <twig:Accordion:Content>\n            We offer standard (5-7 days), express (2-3 days), and overnight\n            shipping. Free shipping on international orders.\n        </twig:Accordion:Content>\n    </twig:Accordion:Item>\n    <twig:Accordion:Item value=\"returns\">\n        <twig:Accordion:Trigger>What is your return policy?</twig:Accordion:Trigger>\n        <twig:Accordion:Content>\n            Returns accepted within 30 days. Items must be unused and in original\n            packaging. Refunds processed within 5-7 business days.\n        </twig:Accordion:Content>\n    </twig:Accordion:Item>\n    <twig:Accordion:Item value=\"support\">\n        <twig:Accordion:Trigger>How can I contact customer support?</twig:Accordion:Trigger>\n        <twig:Accordion:Content>\n            Reach us via email, live chat, or phone. We respond within 24 hours\n            during business days.\n        </twig:Accordion:Content>\n    </twig:Accordion:Item>\n</twig:Accordion>",
    "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, texto text-sm font-medium, a animação grid-template-rows (duration-300 ease-out) e toda a a11y: h3>button, aria-expanded/aria-controls, role=region, aria-labelledby, navegação por setas (up/down conforme orientation) e anel de foco",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "accordion"
        }
    }
}