Input group
Um input com ícones, texto, botões ou uma dica de teclado anexados, compartilhando uma única borda e um único anel de foco.
pnpm dlx shadcn@latest add https://hextaui.com/r/input-group.jsonAdiciona o componente, os tokens de tema do HextaUI e quaisquer componentes do HextaUI dos quais ele depende.
Adicione os tokens de tema ao seu CSS global, se ainda não o fez.
Instale as dependências.
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cnCopie e cole o código a seguir no seu projeto.
components/ui/input-group.tsx components/ui/input.tsx components/ui/button.tsx components/ui/number-flow.tsx lib/motion.ts Atualize os caminhos de importação para corresponder à configuração do seu projeto.
Coloque <InputGroupInput /> ou <InputGroupTextarea /> primeiro e os addons depois. Os addons se posicionam com align, então o campo vem primeiro na ordem de tabulação e para os leitores de tela.
O grupo acompanha seu campo, então as partes inteligentes não precisam de ligação. <InputGroupClear />, <InputGroupPasswordToggle /> e <InputGroupCount /> leem o valor, o type e o maxLength do campo, seja ele controlado ou não.
Ícone
Os ícones ficam dentro da borda em qualquer dos lados. Clicar em um ícone foca o input, então o grupo inteiro parece um único campo.
Limpar
<InputGroupClear /> aparece com fade quando há um valor. Ele limpa pelo histórico de edição do navegador, então Cmd+Z traz o texto de volta, e dispara o seu onChange. Escape também limpa. Um segundo Escape fica para o diálogo ou popover ao redor.
Contagem de caracteres
<InputGroupCount /> conta em relação ao maxLength do campo. Apenas os dígitos que mudam giram. A contagem escurece perto do limite e fica vermelha ao atingi-lo, e uma tecla digitada além do limite a sacode levemente. Os leitores de tela ouvem uma mensagem quando o campo se aproxima do limite e quando o atinge, nunca a cada tecla.
Texto
Use <InputGroupText /> para unidades, moedas e partes de URL. O padding do input diminui ao lado de um addon para que o texto seja lido como um único valor.
Button
<InputGroupButton /> é um botão ghost dimensionado para caber dentro do campo. Seus cantos são concêntricos com os do grupo, e ele tem o próprio anel de foco.
Dica de teclado
Um <kbd> simples dentro de um addon é estilizado como uma tecla. É apenas uma dica visual, então associe o atalho você mesmo.
Textarea
<InputGroupTextarea /> cresce com o conteúdo até 16rem e depois rola. A altura se ajusta suavemente entre as linhas em vez de saltar. Um addon block-end vira uma barra de ferramentas embaixo dele, e os botões nas bordas ganham o mesmo recuo do canto em que estão.
Cabeçalho
Um addon block-start fica acima do campo. Adicione separator para desenhar uma linha fina entre eles.
Senha
<InputGroupPasswordToggle /> alterna um campo type="password" para texto e de volta. O cursor e a seleção permanecem onde estavam, um clique do mouse mantém o foco no campo, e a senha é ocultada de novo quando o formulário é enviado. Controle com revealed.
Tamanhos
size no grupo define a altura e a repassa ao input, correspondendo aos tamanhos de <Input />. Os botões mantêm cantos concêntricos em todos os tamanhos.
Inválido
Defina aria-invalid no input e o grupo inteiro fica vermelho, inclusive seu anel de foco. Vincule a mensagem com aria-describedby.
Desabilitado
Um input desativado esmaece o grupo inteiro e mostra o cursor not-allowed sobre ele. Desative também os botões dos addons, pois do contrário continuam utilizáveis.
Carregando
Os addons inline se ajustam suavemente à nova largura quando o conteúdo muda, então o campo nunca salta quando um spinner vira uma contagem de resultados. O spinner só gira quando o movimento é permitido, e role="status" anuncia o texto.
Dropdown
Renderize um <InputGroupButton /> como gatilho de dropdown para delimitar o escopo do input.
Conteúdo longo
Valores longos rolam dentro do input em vez de esticar o grupo. Envolva textos longos de addon em um span com truncamento e largura máxima.
Da direita para a esquerda
Os addons, o padding e os raios dos cantos usam lados lógicos, então inline-start fica à direita.
| Tecla | Ação |
|---|---|
| Tab | Vai do campo a cada botão de addon, na ordem do código-fonte. |
| ShiftTab | Volta pelos botões e pelo campo. |
| Escape | Com um InputGroupClear, limpa o campo. Quando já está vazio, Escape passa adiante. |
- Todo campo precisa de um nome. Use um rótulo visível, um Field ou
aria-label. Ícones e textos de addon não fazem parte do nome do campo. - Dê aos botões só com ícone um
aria-label. - Quando o texto de um addon carrega significado, como uma moeda ou um domínio, adicione-o ao rótulo ou referencie-o com
aria-describedby. <InputGroupClear />é ignorado na ordem de tabulação porque Escape faz a mesma coisa. O alternador de senha continua tabulável e mantém o mesmo nome, comaria-pressedinformando seu estado.- Quando um envio encontra o campo inválido, o grupo balança uma vez. Com movimento reduzido, a borda vermelha é a única pista.
- Em telas sensíveis ao toque, o texto do campo tem pelo menos 16px para que os celulares não apliquem zoom quando ele recebe foco.
<InputGroupInput /> e <InputGroupTextarea /> aceitam as props dos elementos que renderizam. As outras partes aceitam os atributos do seu elemento.
| Prop | Tipo | Padrão |
|---|---|---|
sizeAltura do grupo, repassada ao input. | "sm" | "default" | "lg" | "default" |
| Atributo | Descrição |
|---|---|
data-slot="input-group" | Seleciona o grupo no CSS. Renderiza role="group". |
data-size | O tamanho atual. |
data-filled | Presente enquanto o campo tem um valor. |
data-shake | Presente enquanto o grupo balança após um envio malsucedido. |
data-disabled | Defina você mesmo para esmaecer o grupo quando apenas os addons estão desativados. |
--input-group-radius | Raio dos cantos do grupo. Botões e teclas derivam o raio deles a partir dele. |
--input-group-height | Altura do grupo para o size atual. |
| Prop | Tipo | Padrão |
|---|---|---|
sizeHerdado do grupo. | "sm" | "default" | "lg" | – |
aria-invalid | boolean | – |
disabled | boolean | false |
readOnly | boolean | false |
| Atributo | Descrição |
|---|---|
data-slot="input-group-control" | Marca o campo. O grupo lê dele os estados de foco, inválido, desativado e somente leitura. |
data-invalid | Presente quando um Field ao redor marca o valor como inválido. |
data-disabled | Presente quando o campo está desativado. |
data-focused | Presente enquanto o campo tem foco. |
data-filled | Presente quando o campo tem um valor. |
data-dirty | Presente quando o valor difere do inicial. |
data-touched | Presente depois que o campo recebeu foco e o perdeu. |
| Prop | Tipo | Padrão |
|---|---|---|
autoResizeCresce com o conteúdo até 16rem, ajustando-se suavemente entre as alturas. | boolean | true |
shakeBalança o grupo quando um envio o encontra inválido. | boolean | true |
rows | number | – |
aria-invalid | boolean | – |
disabled | boolean | false |
| Atributo | Descrição |
|---|---|
data-slot="input-group-control" | Marca o campo. O grupo lê dele os estados de foco, inválido, desativado e somente leitura. |
data-invalid | Presente quando um Field ao redor marca o valor como inválido. |
data-disabled | Presente quando o campo está desativado. |
data-focused | Presente enquanto o campo tem foco. |
data-filled | Presente quando o campo tem um valor. |
data-dirty | Presente quando o valor difere do inicial. |
data-touched | Presente depois que o campo recebeu foco e o perdeu. |
| Prop | Tipo | Padrão |
|---|---|---|
align | "inline-start" | "inline-end" | "block-start" | "block-end" | "inline-start" |
separatorDesenha uma linha fina entre um addon de bloco e o campo. | boolean | false |
| Atributo | Descrição |
|---|---|
data-slot="input-group-addon" | Seleciona os addons no CSS. |
data-align | O alinhamento atual. |
data-separator | Presente quando separator está definido. |
--input-group-addon-inset | Espaço entre a borda do grupo e um botão ou tecla dentro dele. |
| Prop | Tipo | Padrão |
|---|---|---|
variant | "default" | "outline" | "secondary" | "ghost" | "destructive" | "link" | "ghost" |
size | "xs" | "sm" | "icon-xs" | "icon-sm" | "xs" |
type | string | "button" |
feedbackToda prop de Button funciona, inclusive o fluxo de carregamento e sucesso. | boolean | false |
| Atributo | Descrição |
|---|---|
data-slot="input-group-button" | Seleciona os botões de addon no CSS. |
data-size | O tamanho atual. |
| Prop | Tipo | Padrão |
|---|---|---|
onClearChamado depois que o campo é limpo. | () => void | – |
aria-label | string | "Clear" |
children | ReactNode | <IconX /> |
| Atributo | Descrição |
|---|---|
data-slot="input-group-clear" | Seleciona o botão de limpar no CSS. |
data-visible | Presente enquanto o campo tem um valor e é editável. |
| Prop | Tipo | Padrão |
|---|---|---|
revealedEstado controlado. Deixe sem definir para que ele se gerencie sozinho. | boolean | – |
onRevealedChange | (revealed: boolean) => void | – |
aria-label | string | "Show password" |
| Atributo | Descrição |
|---|---|
data-slot="input-group-password-toggle" | Seleciona o alternador no CSS. |
data-revealed | Presente enquanto a senha está visível. |
| Prop | Tipo | Padrão |
|---|---|---|
thresholdCaracteres restantes a partir dos quais a contagem se destaca. | number | 10% of maxLength, at most 20 |
announcementMensagem para leitores de tela quando a contagem cruza o limite ou atinge o máximo. | (remaining: number) => string | – |
| Atributo | Descrição |
|---|---|
data-slot="input-group-count" | Selecione a contagem no CSS. |
data-state="near" | "limit" | Presente dentro do limite e quando não restam caracteres. |
data-bump | Presente brevemente quando uma tecla é pressionada no limite. |
| Atributo | Descrição |
|---|---|
data-slot="input-group-text" | Seleciona o texto de addon no CSS. |
- ButtonBotões em todas as variantes e tamanhos, com um fluxo integrado de carregamento, sucesso e erro que dispensa o spinner em requisições rápidas.
- InputUm campo de texto com três tamanhos, estados inválido e somente leitura, estilo de validação nativa e fonte de 16px no toque para que os celulares nunca façam zoom.
- MotionAs curvas de easing, as durações e a verificação de movimento reduzido com que todo componente anima, além de hooks para transformações de tamanho e destaques deslizantes.
- useAutosizeFaz um textarea crescer conforme o que você escreve entre a altura mínima e a máxima, animando cada mudança sem nunca tocar no texto.
- useComposedRefMantém uma ref para o seu próprio elemento e, ao mesmo tempo, a encaminha para qualquer ref que o pai tenha passado.
- useInvalidShakeSacode um controle de formulário quando uma tentativa de envio o encontra inválido, e nunca enquanto alguém ainda está digitando.
Usado em blocos
Blocos que se baseiam em Input group.
- BillingPlano e uso para um produto de IA, no estilo de Cursor, Claude e Vercel. Um medidor de uso dividido por modelo que projeta o fim do ciclo e avisa antes de os créditos acabarem, um gráfico diário que você pode percorrer, um limite de gastos com alertas que você pode pré-visualizar no medidor, mudanças de plano com proporcional exato, um formulário de cartão com validação real e faturas que baixam como PDF.
- Diff ReviewRevise as edições de um agente em vários arquivos antes que sejam aplicadas. Uma árvore de arquivos com contagens, aceite ou rejeite cada mudança, cada arquivo ou tudo de uma vez, comentários em qualquer linha ou intervalo que voltam para o agente, visões unificada e dividida, destaques por palavra, desfazer, edições em streaming e um resumo "4 arquivos editados" para o chat.
- ModelsA página Modelos das configurações de um produto de IA. Um modelo padrão com contexto, velocidade e custo à primeira vista, um esforço padrão que sabe o que cada modelo suporta, uma lista de modelos pesquisável agrupada por provedor com filtros, fixações e alternâncias em massa, servidores compatíveis com a OpenAI com um teste de conexão real e uma atualização que informa o que há de novo.
- ProfileA seção Perfil das configurações de um produto de IA. Recorte uma foto em um círculo, escolha um nome de usuário que é verificado enquanto você digita, confirme um novo e-mail com um código de 6 dígitos, adicione links que reconhecem o site e veja um card ao vivo de como os outros veem você.