Skip to content

Now in the official shadcn registry directory.

Start free

Input Group

A composable input shell: icons, text prefixes, kbd hints and buttons inside one field. 3 variants, 3 sizes, 3 tones; focus and invalid state lift from the control to the group border.

form
A free styled version is available
https://

Installation

Run the following command

npx shadcn@latest add @ai2/input-group

Dependencies, the @ai2/button component, the @ai2/tokens theme and the component file are installed together.

Usage

TS
import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
import { Search } from "lucide-react"

<InputGroup>
  <InputGroupAddon>
    <Search />
  </InputGroupAddon>
  <InputGroupInput placeholder="Search components" />
</InputGroup>

The group carries the appearance; the inner control is transparent. Set variant, size and tone on InputGroup, and native input props like placeholder, disabled and aria-invalid on InputGroupInput.

Examples

Icon and button

Clicking the leading icon focuses the input; the trailing InputGroupButton keeps its own click handler.

Text prefix and suffix

https://
USD

Kbd hint

⌘K

Textarea with block addon

3,000 characters left

align="block-end" turns the addon into a full-width row under the control and switches the group to auto height. The textarea grows with its content.

Block start addon

Release notes

align="block-start" is the fourth position: a full-width row above the control, useful for headers inside the field. Together with inline-start, inline-end and block-end it completes the align axis.

Variants

Sizes

Tones

The tone axis colors the group border and focus ring. Setting aria-invalid on the inner control alone also lifts the danger border to the group.

Disabled

Set disabled on the inner control. The has-[] selector dims the whole group and blocks pointer events, so addons and buttons go quiet with the field.

Props

InputGroup

InputGroup also accepts every native <div> prop. InputGroupInput and InputGroupTextarea accept every native <input> and <textarea> prop respectively.

PropTypeDefaultDescription
variant"outline" | "soft" | "ghost""outline"Visual style of the group shell, matching the Input variants.
size"sm" | "md" | "lg""md"Height, radius and control typography of the group. The inner control inherits the text scale.
tone"neutral" | "success" | "danger""neutral"Semantic validation color: success and danger recolor the group border and focus ring.

InputGroupAddon

PropTypeDefaultDescription
align"inline-start" | "inline-end" | "block-start" | "block-end""inline-start"Where the addon sits: inline before or after the control, or as a full-width row above or below it.

InputGroupButton

InputGroupButton forwards every ai2 Button prop; only the defaults differ.

PropTypeDefaultDescription
variantButton variant"ghost"Forwarded to the ai2 Button. Ghost keeps the addon quiet inside the field.
sizeButton size"icon-xs"Forwarded to the ai2 Button. icon-xs is a square size-7 button that fits the md group height.

ai2 Input Group: icons, text and buttons inside a react input

The ai2 Input Group is a shadcn-compatible composition of six parts for React, styled with Tailwind CSS v4 on the shared ai2 tokens. The outer InputGroup carries the field appearance with 3 variants (outline, soft, ghost), 3 sizes (sm, md, lg) and 3 tones (neutral, success, danger), while InputGroupInput or InputGroupTextarea render transparent controls inside it and InputGroupAddon places icons, text, kbd hints or buttons around them.

Because it ships through the shadcn registry format, you install it with one CLI command, an MCP agent, or a copy-paste, and the source lands in your own project. You own the file; there is no runtime dependency on ai2 itself. The live example above is the exact component you get.

What is the ai2 Input Group?

It is a role="group" wrapper driven by inputGroupVariants, an exported cva definition with the same variant, size and tone axes as the ai2 Input. The inner control is a bare transparent input or textarea tagged data-slot="input-group-control", and the group watches it with has-[] selectors: focus, disabled and aria-invalid on the control restyle the group border and ring, so the whole field reacts as one control.

Addons are positioned by the align prop: inline-start and inline-end sit beside the control, block-start and block-end become full-width rows above or below it, which is how textarea toolbars are built. Clicking passive addon chrome focuses the control; buttons inside addons keep their own click behavior.

Why use it

  • One focus ring for the whole field: Focus, invalid and disabled state lift from the inner control to the group border via has-[] selectors, so an icon plus input plus button reads as a single control to users.
  • Same three axes as Input: outline, soft and ghost variants, sm, md and lg sizes, neutral, success and danger tones. A grouped field lines up pixel for pixel next to a plain ai2 Input in the same form.
  • Four addon positions: inline-start and inline-end for icons, prefixes and buttons; block-start and block-end for full-width rows like character counters and textarea toolbars.
  • Built on the ai2 Button: InputGroupButton is the real ai2 Button with ghost and icon-xs defaults, so any Button variant, tone or size works inside the field without new APIs.
  • Click-to-focus addons: Clicking passive addon chrome, like a search icon or a https:// prefix, focuses the inner control instead of swallowing the click. Real buttons keep their job.

Features

  • shadcn registry install: One command adds the component, the ai2 Button dependency and the @ai2/tokens theme to your project.
  • Six composable parts: InputGroup, InputGroupInput, InputGroupTextarea, InputGroupAddon, InputGroupText and InputGroupButton. Compose only what the field needs.
  • 3 variants, 3 sizes, 3 tones: outline (default), soft and ghost, each in sm, md and lg with matched height, radius and control typography, plus neutral, success and danger tones on the group border and ring.
  • State lifting via has-[] selectors: focus-visible, disabled and aria-invalid on the inner control restyle the group automatically. No JavaScript state mirroring.
  • Textarea aware: InputGroupTextarea uses field-sizing-content to grow with input, and the group switches to top alignment and auto height when it contains a textarea or a block addon.
  • Icon-family tolerant: The group sizes lucide <svg> icons to size-4 and remixicon <i> glyphs to text-base, so both families sit correctly inside addons.

Production tips

  • Reach for it only when the field has chrome: A bare text field is still the plain ai2 Input. Switch to Input Group when you need an icon, prefix, kbd hint or button inside the same border.
  • Keep aria-invalid on the control: Set aria-invalid on InputGroupInput or InputGroupTextarea, not on the group. The has-[] selector lifts the danger border to the group for you.
  • Label icon-only buttons: InputGroupButton defaults to a square icon-xs ghost button, so an icon-only trigger needs an aria-label to keep the field accessible.
  • Use block addons for textarea toolbars: align="block-end" turns the addon into a full-width row under the textarea, the right place for counters, hints and send or mic buttons.
  • Push trailing content with ml-auto: Inside a block addon, add ml-auto to the last button to split a leading counter from trailing actions, as in the textarea example above.

Works with the rest of ai2

Input Group extends the form kit. Wrap it in an ai2 Field for label, description and error placement, drop an ai2 Kbd into a trailing addon for shortcut hints, and use the ai2 Button API directly through InputGroupButton.

For a plain field without addons, stay on the Input or Textarea, which share the same variant, size and tone language. For file uploads, use the FileInput component instead of grouping a file input.

FAQs

Get new components in your inbox

Component drops, new themes and release notes. No spam, and you can unsubscribe from any email.

© 2026 ai2 design system · MIT licensed · Built with its own components