Skip to content

Input Group

Stable

An input with icons, text, buttons or keyboard hints attached — bordered, focused and validated as a single control.

⌘K

Anatomy

https://
  1. 1GroupOne bordered field that owns the focus halo, so the addons and the input read as a single control.
  2. 2Leading addonText or an icon before the input: a protocol, a currency, a search icon. Clicking it focuses the input.
  3. 3ControlThe input or textarea itself, borderless inside the group.
  4. 4Trailing addonA button, a unit or a keyboard hint after the input.

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/input-group.json

Usage

import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
  InputGroupText,
} from "@/components/ui/input-group"
<InputGroup>
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
  <InputGroupInput placeholder="Search…" />
</InputGroup>

Inside a group, use InputGroupInput and InputGroupTextarea — never a plain Input. The group owns the border, fill, focus halo and invalid state; the inner control is deliberately bare.

Examples

Text addons

Prefixes and suffixes carry units and fixed parts of a value — a currency, a domain — so people type only what's variable. Wrap text in InputGroupText.

.prfct.dev
$
USD

Buttons

InputGroupButton is a compact ghost Button sized to sit inside the field: copy a value, reveal a password, clear a query. Icon-only buttons need an aria-label; toggles like Show password also report aria-pressed.

Status

Addons can report what's happening to the value — checking availability with a Spinner, then confirming with an icon. Always repeat the status in text below the field; an icon alone isn't enough.

@
@

Composer

With InputGroupTextarea and a block-end addon, the group becomes a message composer: the field grows with the text while attachments, hints and the send action stay pinned below it.

Enter to send · Shift + Enter for a new line

Block addons

block-start addons sit above the control, full width — a file name above a code editor, a toolbar above a note. Add border-b to separate them.

webhook-payload.json

Guidelines

When to use

  • Units, prefixes and suffixes that are part of the value: $, USD, .prfct.dev, https://.
  • Actions that operate on the value itself: copy, reveal, clear, submit a search.
  • Signals about the value: a leading search icon, a validation status, a keyboard shortcut hint.

When not to use

  • Actions that aren't about the value, like Save or Cancel — put a Button next to the field instead.
  • More than two addons on one side. A crowded field is hard to scan and leaves little room to type.
  • Multi-line rich editing with formatting — use a dedicated editor.

Keep addons honest

A leading icon should clarify what the field is for, not decorate it. If it's interactive, it must be an InputGroupButton with a label — a clickable-looking icon that does nothing is a trap.

.prfct.dev
Do.Text addons carry the fixed parts; people type only the variable one.
Don’t.Asking for the full URL invites typos in parts people shouldn’t have to type.

Accessibility

  • One control, one name. Label the InputGroupInput with a FieldLabel and htmlFor/id, or aria-label. Addon text like USD is not part of the name — mention the unit in the label or description when it matters.
  • Grouping. The group and each addon render role="group"; clicking an addon's empty space focuses the input.
  • Focus and state. The whole group shows the brand focus halo while its control has keyboard focus, and turns red when the control has aria-invalid.
  • Buttons. InputGroupButton is a real button with type="button" by default, so it never submits a form by accident.
  • Shortcuts. A Kbd hint is visual only. Make the shortcut discoverable elsewhere too, such as in a tooltip or a help page.
KeyBehavior
Tab
Moves focus to the input, then to each button in the group.
EnterSpace
Activates a focused InputGroupButton.

API reference

InputGroup

Renders a <div role="group"> that draws the border, fill and focus state. Accepts all div props.

InputGroupAddon

Renders a <div role="group"> that holds icons, text, buttons or Kbd hints.

PropTypeDefault
align

Before or after the control on its line, or above or below it at full width.

"inline-start" | "inline-end" | "block-start" | "block-end""inline-start"

InputGroupButton

Renders a Button sized for the group. Accepts all Button props; size takes the group's own sizes, listed below.

PropTypeDefault
size

24 or 28px tall; icon sizes are square.

"xs" | "sm" | "icon-xs" | "icon-sm""xs"
variant

Any Button variant. Use default for a primary action such as Send.

Button variant"ghost"
type

Defaults to button so it never submits a form by accident.

"button" | "submit" | "reset""button"

InputGroupText

Renders a <span> for text and icons in muted-foreground.

InputGroupInput

Renders a borderless Base UI Input. Accepts all native input props.

InputGroupTextarea

Renders a borderless <textarea> that grows with its content. Accepts all native textarea props.