Summit
ComponentsFields

Input Group

An Input Group displays icons, text, and Buttons inside the edge of an Input or a Textarea so that users see them as part of the field.

When to Use

  • to mark a search box with an icon
  • to show a fixed part of the value next to it, such as “USD” or “.example.com”
  • for a Button that acts on the value, such as “Copy the payment link” or “Show the password”
  • for a message box, with a Textarea and “Send” in a row under the text
  • for a keyboard shortcut in an addon, with a Kbd

When Not to Use

  • for a Button next to the Input and outside its edge (use an Input and a Button in a row)
  • for a Button or text joined to the outside of an Input (use a Button Group)
  • to filter a list by typing (use a Combobox, which is built on an Input Group)
  • for the label above the control and the error under it (wrap the group in a Field)

Anatomy

120 characters left
ElementUsage
Inline addonOptional
ControlRequired
ContainerRequired
ButtonOptional
Block addonOptional
TextOptional

Write the control first and its addons after it so that keyboard users reach the control with Tab before a Button in an addon. align sets the position of an addon, wherever it is in the markup.

AlignPosition
inline-startBefore the control, on its line. The default.
inline-endAfter the control, on its line
block-startA row above the control
block-endA row below the control

Sizes

An Input Group has no size prop. It grows when it has a block addon or a Textarea. InputGroupButton has sizes of its own.

SizeHeightPlacement
xs24pxA text Button in an inline addon. The default.
icon-xs24pxAn icon-only Button in an inline addon
sm32pxA text Button in a block addon
icon-sm32pxAn icon-only Button in a block addon

sm and icon-sm are as tall as the group itself, so use them only in a block addon.

DoUse xs for a Button in an inline addon; it is 24px tall and fits inside the edge.
Don’tWhen sm is set in an inline addon, the Button is 32px tall and covers the top and bottom edges of the group.

States

Set disabled and aria-invalid on the control. The group shows the states of its control.

Behavior

When users click an addon outside a Button, the group’s Input or Textarea receives focus.

Accessibility

The group and its addons are div elements with role="group" and no name. The control and the Buttons are native elements and keep their own keys.

The control of an Input Group needs a name so that screen readers can announce it, as WCAG 2.2 SC 4.1.2 Name, Role, Value requires. To provide one, place it in a Field with a FieldLabel, connect a Label to its id with htmlFor, or set aria-label. An icon or a unit in an addon doesn’t name the control.

An icon-only InputGroupButton needs an aria-label and a Tooltip, as an icon-only Button does.

Installation

npx shadcn@latest add @summit/input-group

The CLI also adds @summit/button, @summit/input, and @summit/textarea.

Usage

import { InputGroup, InputGroupAddon, InputGroupInput, InputGroupText } from '@/components/ui/input-group';

<InputGroup>
    <InputGroupInput aria-label="Amount" inputMode="decimal" placeholder="0.00" />
    <InputGroupAddon align="inline-end">
        <InputGroupText>USD</InputGroupText>
    </InputGroupAddon>
</InputGroup>;

With a Button

By default, InputGroupButton is a ghost Button at xs. For an icon-only Button, set size="icon-xs" and an aria-label.

With a Button
import { CopyIcon } from '@phosphor-icons/react';

<InputGroup>
    <InputGroupInput aria-label="Payment link" defaultValue="https://pay.example.com/inv-2026-014" readOnly />
    <InputGroupAddon align="inline-end">
        <InputGroupButton size="icon-xs" aria-label="Copy the payment link">
            <CopyIcon />
        </InputGroupButton>
    </InputGroupAddon>
</InputGroup>;

With a Textarea

For a message box, use InputGroupTextarea and a block-end addon. To move a child and everything after it to the end of the row, add ms-auto to that child.

With a Textarea
<InputGroup>
    <InputGroupTextarea aria-label="Message" placeholder="Write a message to the client" />
    <InputGroupAddon align="block-end">
        <InputGroupText className="ms-auto text-xs">120 characters left</InputGroupText>
        <InputGroupButton size="sm" variant="default">
            Send
        </InputGroupButton>
    </InputGroupAddon>
</InputGroup>

With a Label Inside

To name the control from inside the edge, place a Label in an addon and point its htmlFor at the control. The control then doesn’t need an aria-label.

With a Label Inside
import { Label } from '@/components/ui/label';

<InputGroup>
    <InputGroupInput id="to" type="email" />
    <InputGroupAddon>
        <Label htmlFor="to">To</Label>
    </InputGroupAddon>
</InputGroup>;

API Reference

InputGroup finds its control by data-slot="input-group-control". If you build a control outside the registry, add that attribute so that the group shows its focus outline, invalid border, and disabled state.

InputGroupAddon

PropTypeDefaultDescription
align'inline-start' | 'inline-end' | 'block-start' | 'block-end''inline-start'The side of the control where the addon is placed

InputGroupButton

PropTypeDefaultDescription
size'xs' | 'sm' | 'icon-xs' | 'icon-sm''xs'The height and the padding
variantA variant of a Button'ghost'The fill and the text color
type'button' | 'submit' | 'reset''button'The type attribute of the button element

Other props of InputGroupButton are passed to the Button that it renders.

On this page