Pular para o conteúdo

Select

templates/components/Select

É um `<select>` NATIVO do sistema (não um popover/combobox em JS): a escolha acontece entre `<option>`/`<optgroup>` nativos filhos, com type-ahead, foco e a11y nativos do navegador. Por isso todo enricher trabalha pela SEMÂNTICA das opções e pelo comportamento de formulário nativo — nunca injetando ícones/HTML rico nas opções (isso exigiria outra base).

Base congelada

Conteúdo

Agrupar opções (optgroup)

Organiza as opções em seções nativas…

Organiza as opções em seções nativas <optgroup label> (ex.: Frutas / Verduras), sem tocar no visual do campo.

Valor padrão

Define qual opção já vem escolhida…

Define qual opção já vem escolhida (atributo selected) ao carregar, no lugar do placeholder.

Multi-seleção (multiple) ⚠️

Permite escolher várias opções via atributo…

Permite escolher várias opções via atributo multiple nativo. REPROVADO no teste: o multiple nativo transforma a caixa h-10 num listbox alto e rolável, quebrando altura/forma congeladas — exigiria outra base.

Comportamento

Placeholder

Opção-guia inicial (value vazio, disabled+selected) em…

Opção-guia inicial (value vazio, disabled+selected) em texto suave; ex.: "Selecione…". Reaproveita o data-[placeholder] já existente na base.

Opções desabilitadas

Marca opções específicas como não-selecionáveis (disabled)…

Marca opções específicas como não-selecionáveis (disabled) mantendo-as visíveis; ex.: item sem estoque.

Ordenar opções

Reordena as <option> na renderização —…

Reordena as <option> na renderização — alfabética crescente/decrescente ou ordem original — útil em listas longas. Espelha o precedente de Ordenar da Tabela.

Seleção obrigatória

Atributo required: bloqueia o envio do…

Atributo required: bloqueia o envio do formulário enquanto o placeholder (value vazio) estiver selecionado. Validação nativa, sem mudar o estado visual em repouso.

Auto-enviar ao mudar

Ao trocar a opção, envia o…

Ao trocar a opção, envia o formulário pai (selects de filtro/ordenação/idioma). Progressive enhancement via Stimulus; só comportamento.
Código gerado

Cole no Claude Code — ele acerta de primeira.

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

BASE CONGELADA (não mude por instância): O elemento `<select>` nativo e sua casca shadcn: h-10, w-full, rounded-md, border border-input, bg-background, px-3 py-2, text-sm, ring-offset-background; cor do placeholder via data-[placeholder]:text-muted-foreground; foco com focus:ring-2 ring-ring ring-offset-2; disabled:cursor-not-allowed disabled:opacity-50; [&>span]:line-clamp-1; a seta nativa do dropdown; e toda a a11y/UX nativa (papel de combobox, busca por digitação/type-ahead, navegação por teclado, foco visível). Nada disso muda ao ligar/desligar capacidade.

USO: <twig:Select />

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Placeholder: Opção-guia inicial (value vazio, disabled+selected) em texto suave; ex.: "Selecione…". Reaproveita o data-[placeholder] já existente na base. [text]- Agrupar opções (optgroup): Organiza as opções em seções nativas <optgroup label> (ex.: Frutas / Verduras), sem tocar no visual do campo. [toggle]- Opções desabilitadas: Marca opções específicas como não-selecionáveis (disabled) mantendo-as visíveis; ex.: item sem estoque. [multi → Apple / Banana / Blueberry / Grapes / Pineapple]- Valor padrão: Define qual opção já vem escolhida (atributo selected) ao carregar, no lugar do placeholder. [select → Apple / Banana / Blueberry / Grapes / Pineapple]- Ordenar opções: Reordena as <option> na renderização — alfabética crescente/decrescente ou ordem original — útil em listas longas. Espelha o precedente de Ordenar da Tabela. [select → A→Z / Z→A / Ordem original]- Seleção obrigatória: Atributo required: bloqueia o envio do formulário enquanto o placeholder (value vazio) estiver selecionado. Validação nativa, sem mudar o estado visual em repouso. [toggle]- Auto-enviar ao mudar: Ao trocar a opção, envia o formulário pai (selects de filtro/ordenação/idioma). Progressive enhancement via Stimulus; só comportamento. [toggle]- Multi-seleção (multiple): Permite escolher várias opções via atributo multiple nativo. REPROVADO no teste: o multiple nativo transforma a caixa h-10 num listbox alto e rolável, quebrando altura/forma congeladas — exigiria outra base. [toggle]  (⚠️ 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): foco com focus:ring-2 ring-ring ring-offset-2. e toda a a11y/UX nativa (papel de combobox, busca por digitação/type-ahead, navegação por teclado, foco visível)

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

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

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "select",
    "component": "Select",
    "eixo": "ux",
    "particularidade": "É um `<select>` NATIVO do sistema (não um popover/combobox em JS): a escolha acontece entre `<option>`/`<optgroup>` nativos filhos, com type-ahead, foco e a11y nativos do navegador. Por isso todo enricher trabalha pela SEMÂNTICA das opções e pelo comportamento de formulário nativo — nunca injetando ícones/HTML rico nas opções (isso exigiria outra base).",
    "base_congelada": "O elemento `<select>` nativo e sua casca shadcn: h-10, w-full, rounded-md, border border-input, bg-background, px-3 py-2, text-sm, ring-offset-background; cor do placeholder via data-[placeholder]:text-muted-foreground; foco com focus:ring-2 ring-ring ring-offset-2; disabled:cursor-not-allowed disabled:opacity-50; [&>span]:line-clamp-1; a seta nativa do dropdown; e toda a a11y/UX nativa (papel de combobox, busca por digitação/type-ahead, navegação por teclado, foco visível). Nada disso muda ao ligar/desligar capacidade.",
    "props": [],
    "capacidades": [
        {
            "id": "placeholder",
            "nome": "Placeholder",
            "descricao": "Opção-guia inicial (value vazio, disabled+selected) em texto suave; ex.: \"Selecione…\". Reaproveita o data-[placeholder] já existente na base.",
            "controle": "text",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (text). Ligue no configurador em /vitrine/ux/select; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "agrupar-op-es-optgroup",
            "nome": "Agrupar opções (optgroup)",
            "descricao": "Organiza as opções em seções nativas <optgroup label> (ex.: Frutas / Verduras), sem tocar no visual do campo.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/select; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "op-es-desabilitadas",
            "nome": "Opções desabilitadas",
            "descricao": "Marca opções específicas como não-selecionáveis (disabled) mantendo-as visíveis; ex.: item sem estoque.",
            "controle": "multi",
            "opcoes": [
                "Apple",
                "Banana",
                "Blueberry",
                "Grapes",
                "Pineapple"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (multi). Ligue no configurador em /vitrine/ux/select; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "valor-padr-o",
            "nome": "Valor padrão",
            "descricao": "Define qual opção já vem escolhida (atributo selected) ao carregar, no lugar do placeholder.",
            "controle": "select",
            "opcoes": [
                "Apple",
                "Banana",
                "Blueberry",
                "Grapes",
                "Pineapple"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ux/select; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "ordenar-op-es",
            "nome": "Ordenar opções",
            "descricao": "Reordena as <option> na renderização — alfabética crescente/decrescente ou ordem original — útil em listas longas. Espelha o precedente de Ordenar da Tabela.",
            "controle": "select",
            "opcoes": [
                "A→Z",
                "Z→A",
                "Ordem original"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ux/select; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "sele-o-obrigat-ria",
            "nome": "Seleção obrigatória",
            "descricao": "Atributo required: bloqueia o envio do formulário enquanto o placeholder (value vazio) estiver selecionado. Validação nativa, sem mudar o estado visual em repouso.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/select; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "auto-enviar-ao-mudar",
            "nome": "Auto-enviar ao mudar",
            "descricao": "Ao trocar a opção, envia o formulário pai (selects de filtro/ordenação/idioma). Progressive enhancement via Stimulus; só comportamento.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ux/select; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "multi-sele-o-multiple",
            "nome": "Multi-seleção (multiple)",
            "descricao": "Permite escolher várias opções via atributo multiple nativo. REPROVADO no teste: o multiple nativo transforma a caixa h-10 num listbox alto e rolável, quebrando altura/forma congeladas — exigiria outra base.",
            "controle": "toggle",
            "opcoes": [],
            "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:Select />",
    "exemplo_demo": "<twig:Select class=\"max-w-xs\">\n    <option value=\"apple\">Apple</option>\n    <option value=\"banana\">Banana</option>\n    <option value=\"blueberry\">Blueberry</option>\n    <option value=\"grapes\">Grapes</option>\n    <option value=\"pineapple\">Pineapple</option>\n</twig:Select>",
    "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": "foco com focus:ring-2 ring-ring ring-offset-2. e toda a a11y/UX nativa (papel de combobox, busca por digitação/type-ahead, navegação por teclado, foco visível)",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "select"
        }
    },
    "props_nota": "Sem props próprias declaradas: a base repassa atributos nativos via {{ attributes }} (id, name, type, value, aria-*, data-*). Props específicas, quando existem, ficam nos subcomponentes."
}