Pular para o conteúdo

Input Group

templates/components/InputGroup

O InputGroup não é um input: é o CONTÊINER de composição que une um único controle (Input ou Textarea) e vários addons dentro de uma mesma moldura, com 4 slots posicionais (inline-start/end, block-start/end) que abrigam ícone, texto, botão ou kbd compartilhando um só anel de foco e um só estado inválido. Prefixo, sufixo e ícone JÁ são a base dele; por isso os enriquecedores são comportamentos montados nesses slots existentes, nunca novos visuais.

Base congelada

12 results

Conteúdo

Máscara de entrada

Formata o valor do controle enquanto…

Formata o valor do controle enquanto se digita (locale BR); muda o texto, nunca o visual.

Mostrar/ocultar senha

Addon-botão de olho no slot inline-end…

Addon-botão de olho no slot inline-end que alterna o controle entre oculto e visível.

Contador de caracteres

Addon que exibe 'N/máx' ao vivo;…

Addon que exibe 'N/máx' ao vivo; opcionalmente aciona o estado inválido da base ao ultrapassar o limite. posicionável

Comportamento

Botão limpar

Addon-botão (x) montado no slot inline-end…

Addon-botão (x) montado no slot inline-end que aparece quando há conteúdo e esvazia o controle num clique.

Copiar conteúdo

Addon-botão que copia o valor do…

Addon-botão que copia o valor do controle para a área de transferência, com feedback de check (ideal para códigos/tokens read-only). posicionável

Atalho de teclado (foco)

Mostra a tecla num <kbd> (já…

Mostra a tecla num <kbd> (já estilizado pela base) num addon e liga esse atalho para focar o controle do grupo. posicionável

Ícone de estado (validação)

Roda uma regra ao sair do…

Roda uma regra ao sair do campo, alterna aria-invalid e mostra um ícone de erro/ok num addon, reaproveitando o estado inválido já existente na base.

Auto-crescer (Textarea)

No modo Textarea, cresce a altura…

No modo Textarea, cresce a altura conforme o conteúdo até um limite, mantendo o resize-none da base.
Código gerado

Cole no Claude Code — ele acerta de primeira.

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

BASE CONGELADA (não mude por instância): Moldura h-8 arredondada (rounded-lg) com border-input; anel de foco único (focus-within ring-3 ring-ring) e estado inválido único (aria-invalid -> border/ring destructive); opacidade 50% quando disabled. Os 4 slots de alinhamento e seus paddings LTR/RTL, o gap-2, a tipografia dos addons (text-sm font-medium text-muted-foreground), o raio do kbd, os tamanhos de botão (xs/icon-xs) e o Textarea com resize-none + altura automática permanecem imutáveis. Ligar/desligar qualquer capacidade não altera fonte, cor, cantos nem espaçamento — só monta comportamento nos slots já existentes.

USO: <twig:InputGroup />

CAPACIDADES OPT-IN (ligue sem alterar o visual):
- Máscara de entrada: Formata o valor do controle enquanto se digita (locale BR); muda o texto, nunca o visual. [select → CPF / CNPJ / CPF/CNPJ / Telefone / CEP / Moeda (R$) / Data (dd/mm/aaaa) / Placa Mercosul / Cartão]- Botão limpar: Addon-botão (x) montado no slot inline-end que aparece quando há conteúdo e esvazia o controle num clique. [toggle]- Mostrar/ocultar senha: Addon-botão de olho no slot inline-end que alterna o controle entre oculto e visível. [toggle]- Copiar conteúdo: Addon-botão que copia o valor do controle para a área de transferência, com feedback de check (ideal para códigos/tokens read-only). [toggle]- Contador de caracteres: Addon que exibe 'N/máx' ao vivo; opcionalmente aciona o estado inválido da base ao ultrapassar o limite. [number]- Atalho de teclado (foco): Mostra a tecla num <kbd> (já estilizado pela base) num addon e liga esse atalho para focar o controle do grupo. [text]- Ícone de estado (validação): Roda uma regra ao sair do campo, alterna aria-invalid e mostra um ícone de erro/ok num addon, reaproveitando o estado inválido já existente na base. [toggle]- Auto-crescer (Textarea): No modo Textarea, cresce a altura conforme o conteúdo até um limite, mantendo o resize-none da base. [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): anel de foco único (focus-within ring-3 ring-ring) e estado inválido único (aria-invalid -> border/ring destructive)

Via MCP: tool get_component com {"id": "input-group"} · list_capabilities("input-group").

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

Spec machine-readable (JSON)

{
    "$schema_version": "1.0",
    "id": "input-group",
    "component": "InputGroup",
    "eixo": "ui",
    "particularidade": "O InputGroup não é um input: é o CONTÊINER de composição que une um único controle (Input ou Textarea) e vários addons dentro de uma mesma moldura, com 4 slots posicionais (inline-start/end, block-start/end) que abrigam ícone, texto, botão ou kbd compartilhando um só anel de foco e um só estado inválido. Prefixo, sufixo e ícone JÁ são a base dele; por isso os enriquecedores são comportamentos montados nesses slots existentes, nunca novos visuais.",
    "base_congelada": "Moldura h-8 arredondada (rounded-lg) com border-input; anel de foco único (focus-within ring-3 ring-ring) e estado inválido único (aria-invalid -> border/ring destructive); opacidade 50% quando disabled. Os 4 slots de alinhamento e seus paddings LTR/RTL, o gap-2, a tipografia dos addons (text-sm font-medium text-muted-foreground), o raio do kbd, os tamanhos de botão (xs/icon-xs) e o Textarea com resize-none + altura automática permanecem imutáveis. Ligar/desligar qualquer capacidade não altera fonte, cor, cantos nem espaçamento — só monta comportamento nos slots já existentes.",
    "props": [],
    "capacidades": [
        {
            "id": "m-scara-de-entrada",
            "nome": "Máscara de entrada",
            "descricao": "Formata o valor do controle enquanto se digita (locale BR); muda o texto, nunca o visual.",
            "controle": "select",
            "opcoes": [
                "CPF",
                "CNPJ",
                "CPF/CNPJ",
                "Telefone",
                "CEP",
                "Moeda (R$)",
                "Data (dd/mm/aaaa)",
                "Placa Mercosul",
                "Cartão"
            ],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (select). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "bot-o-limpar",
            "nome": "Botão limpar",
            "descricao": "Addon-botão (x) montado no slot inline-end que aparece quando há conteúdo e esvazia o controle num clique.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "mostrar-ocultar-senha",
            "nome": "Mostrar/ocultar senha",
            "descricao": "Addon-botão de olho no slot inline-end que alterna o controle entre oculto e visível.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "copiar-conte-do",
            "nome": "Copiar conteúdo",
            "descricao": "Addon-botão que copia o valor do controle para a área de transferência, com feedback de check (ideal para códigos/tokens read-only).",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "contador-de-caracteres",
            "nome": "Contador de caracteres",
            "descricao": "Addon que exibe 'N/máx' ao vivo; opcionalmente aciona o estado inválido da base ao ultrapassar o limite.",
            "controle": "number",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (number). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "atalho-de-teclado-foco",
            "nome": "Atalho de teclado (foco)",
            "descricao": "Mostra a tecla num <kbd> (já estilizado pela base) num addon e liga esse atalho para focar o controle do grupo.",
            "controle": "text",
            "opcoes": [],
            "posicionavel": true,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (text). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "cone-de-estado-valida-o",
            "nome": "Ícone de estado (validação)",
            "descricao": "Roda uma regra ao sair do campo, alterna aria-invalid e mostra um ícone de erro/ok num addon, reaproveitando o estado inválido já existente na base.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        },
        {
            "id": "auto-crescer-textarea",
            "nome": "Auto-crescer (Textarea)",
            "descricao": "No modo Textarea, cresce a altura conforme o conteúdo até um limite, mantendo o resize-none da base.",
            "controle": "toggle",
            "opcoes": [],
            "posicionavel": false,
            "e_funcao": true,
            "como_plugar": "Capacidade opt-in (toggle). Ligue no configurador em /vitrine/ui/input-group; comportamento via controller Stimulus. Não altera a base."
        }
    ],
    "snippet_uso": "<twig:InputGroup />",
    "exemplo_demo": "<twig:InputGroup class=\"max-w-xs\">\n    <twig:InputGroup:Input placeholder=\"Search...\" />\n    <twig:InputGroup:Addon>\n        <twig:ux:icon name=\"lucide:search\" />\n    </twig:InputGroup:Addon>\n    <twig:InputGroup:Addon align=\"inline-end\">12 results</twig:InputGroup:Addon>\n</twig:InputGroup>",
    "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": "anel de foco único (focus-within ring-3 ring-ring) e estado inválido único (aria-invalid -> border/ring destructive)",
    "mcp": {
        "tool": "get_component",
        "args": {
            "id": "input-group"
        }
    },
    "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."
}