Uranus® Design System

InputGroup

Input com adornos inline ou block para ícones, prefixos e ações

InputGroup compõe um Input com adornos — ícones, texto descritivo, botões inline ou controles adjacentes — mantendo uma única borda visual e um único anel de foco. Use sempre que o campo precisar de uma afordance extra que não caiba dentro do input cru.

import { InputGroup, InputGroupAddon, InputGroupInput } from '@uranus-workspace/design-system';
import { Search } from 'lucide-react';

export default function InputGroupDefault() {
  return (
    <InputGroup className="w-full max-w-sm">
      <InputGroupAddon>
        <Search className="size-4" />
      </InputGroupAddon>
      <InputGroupInput placeholder="Buscar na Uranus…" />
    </InputGroup>
  );
}

Anatomia

  • InputGroup — contêiner raiz com role="group". Renderiza a borda e o foco compartilhado.
  • InputGroupInput — o Input interno, sem borda própria.
  • InputGroupTextarea — variante para quando o controle é multi-linha.
  • InputGroupAddon — um slot para ícone, texto ou botão. Aceita align="inline-start" | "inline-end" | "block-start" | "block-end".
  • InputGroupText — um span com tipografia text-muted-foreground para prefixos/sufixos textuais.
  • InputGroupButton — um botão compacto otimizado para caber dentro do grupo. Aceita size="xs" | "sm" | "icon-xs" | "icon-sm".

Ícones, prefixos e ações

O alinhamento do InputGroupAddon determina se o adorno fica antes ou depois do input. Combine um ícone do Lucide com um InputGroupText para prefixos como https://, ou coloque um InputGroupButton no final para ações inline.

https://
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
  InputGroupText,
} from '@uranus-workspace/design-system';
import { ArrowRight, Globe } from 'lucide-react';

export default function InputGroupButtonExample() {
  return (
    <div className="flex w-full max-w-md flex-col gap-4">
      <InputGroup>
        <InputGroupAddon>
          <Globe className="size-4" />
          <InputGroupText>https://</InputGroupText>
        </InputGroupAddon>
        <InputGroupInput placeholder="uranus.com.br" />
      </InputGroup>
      <InputGroup>
        <InputGroupInput type="email" placeholder="voce@uranus.com.br" />
        <InputGroupAddon align="inline-end">
          <InputGroupButton variant="primary" size="sm">
            Entrar
            <ArrowRight className="size-4" />
          </InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
    </div>
  );
}

Uso

import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from '@uranus-workspace/design-system';
import { Search } from 'lucide-react';

<InputGroup>
  <InputGroupAddon>
    <Search className="size-4" />
  </InputGroupAddon>
  <InputGroupInput placeholder="Buscar…" />
</InputGroup>

Faça

  • Use um único adorno de cada lado — dois ícones no mesmo lado tornam o campo ilegível.
  • Prefira InputGroupButton sobre um Button solto — ele já tem os tamanhos certos para caber no grupo.
  • Mantenha o Label fora do InputGroup, acima dele, associado ao InputGroupInput via id/htmlFor.

Não faça

  • Não empilhe vários InputGroups lado a lado sem gap — eles precisam de espaço para respirar.
  • Não use adornos apenas decorativos sem aria-hidden quando forem puramente visuais.
  • Não duplique a borda passando border no InputGroupInput — o grupo já renderiza a borda única.

Acessibilidade

  • O contêiner tem role="group", então leitores de tela anunciam o conjunto como uma unidade.
  • O foco visível é compartilhado: qualquer controle interno focado produz o mesmo ring, evitando duas bordas de foco conflitantes.
  • Quando o input é inválido (aria-invalid="true"), o grupo inteiro adota o estilo destrutivo.