---
title: Input Group
description: Adds icons, text, buttons or keyboard hints before or after an input or textarea, so extra information and actions sit inside the same control.
icon: group
author:
  name: shadcn
  url: https://github.com/shadcn
mode: wide
---

<PoweredBy packages={[{ name: 'Shadcn UI', url: 'https://ui.shadcn.com/docs/components/input-group' }]} />

### Installation

```package-install
npx shadcn@latest add @redpanda/input-group
```

<ComponentPreview name="input-group-demo" />

## When to use

Use this decision tree to determine when to use the Input Group component:

```mermaid
graph TD;
    A[❓ Need input with addons?] -->|Yes| B{Just label/description?};
    A -->|No| C[ℹ️ Use plain Input];
    B -->|Yes| D[ℹ️ Use Field component];
    B -->|No| E{Icons or buttons inline?};
    E -->|Yes| F[✅ Use InputGroup];
    F --> G{Need icons?};
    G -->|Yes| H[✅ Add icon in InputGroupAddon];
    F --> I{Need buttons?};
    I -->|Yes| J[✅ Add InputGroupButton];
    F --> K{Textarea input?};
    K -->|Yes| L[✅ Use InputGroupTextarea];
    K -->|No| M[✅ Use InputGroupInput];
    F --> N{Loading state?};
    N -->|Yes| O[✅ Add Spinner in addon];

    classDef recommended fill:#4ade80,stroke:#22c55e,stroke-width:2px,color:#000;
    classDef discouraged fill:#fbbf24,stroke:#f59e0b,stroke-width:2px,color:#000;
    classDef decision fill:#60a5fa,stroke:#3b82f6,stroke-width:2px,color:#fff;
    classDef neutral fill:#9ca3af,stroke:#6b7280,stroke-width:2px,color:#fff;

    class F,H,J,L,M,O recommended;
    class D discouraged;
    class A,B,E,G,I,K,N decision;
    class C neutral;
```

## Usage

```tsx lineNumbers
import {
  InputGroup,
  InputGroupAddon,
  InputGroupButton,
  InputGroupInput,
  InputGroupText,
  InputGroupTextarea,
} from '@/components/ui/input-group';
```

```tsx lineNumbers
<InputGroup>
  <InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
  <InputGroupAddon align="inline-end">
    <InputGroupButton>Search</InputGroupButton>
  </InputGroupAddon>
</InputGroup>
```

## Anatomy

The InputGroup component enhances inputs with inline addons. Here's how the components work together:

```tsx
<InputGroup>            {/* Container with unified focus state */}
  <InputGroupAddon      {/* Addon positioned at inline-start */}
    align="inline-start">
    <SearchIcon />      {/* Icon, text, or button */}
  </InputGroupAddon>
  <InputGroupInput />   {/* Styled input (replaces Input) */}
  <InputGroupAddon      {/* Addon positioned at inline-end */}
    align="inline-end">
    <InputGroupButton>  {/* Button in addon */}
      Search
    </InputGroupButton>
  </InputGroupAddon>
</InputGroup>
```

### Layout Structure

- **InputGroup**: Root container with `role="group"` and unified focus ring
- **InputGroupInput**: Replacement for `<Input />` with group-specific styles
- **InputGroupTextarea**: Replacement for `<Textarea />` with group-specific styles
- **InputGroupAddon**: Container for icons, text, or buttons alongside the input
- **InputGroupButton**: Styled button optimized for input groups (smaller sizes)
- **InputGroupText**: Text content that can be displayed in addons

Use `shape="pill"` on `InputGroup` for a fully rounded URL field. Its actions separately support the inherited
`InputGroupButton shape="pill"` contract; no local radius variables or rounded-class overrides are needed.

For textarea chrome, use `separator` on a `block-start` or `block-end` addon. The addon owns the adjacent border
and its padding. Inline addons do not accept a separator. Use a semantic `<code>` inside `InputGroupText` for a
filename rather than overriding the text primitive's typography.

Place a popover trigger directly on the native `InputGroupButton`, not on an addon wrapping that button.
Information-only icons use a named `Popover`, with optional `openOnHover`, so keyboard and touch users can open
the content. Tooltips are only supplementary visual labels for independently named actions. Stateful favorites
expose `aria-pressed` on that native action.

### Alignment Options

InputGroupAddon supports four alignment positions via the `align` prop:

- **inline-start** (default): Left side of input (or right in RTL)
- **inline-end**: Right side of input (or left in RTL)
- **block-start**: Top of textarea
- **block-end**: Bottom of textarea

### Typical Usage Patterns

```tsx expandable
// Input with leading icon
<InputGroup>
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
  <InputGroupInput placeholder="Search..." />
</InputGroup>

// Input with trailing button
<InputGroup>
  <InputGroupInput placeholder="Enter email..." />
  <InputGroupAddon align="inline-end">
    <InputGroupButton>Subscribe</InputGroupButton>
  </InputGroupAddon>
</InputGroup>

// Input with both sides
<InputGroup>
  <InputGroupAddon>
    <DollarIcon />
  </InputGroupAddon>
  <InputGroupInput placeholder="0.00" />
  <InputGroupAddon align="inline-end">
    <InputGroupText>USD</InputGroupText>
  </InputGroupAddon>
</InputGroup>

// Textarea with button at bottom
<InputGroup>
  <InputGroupTextarea placeholder="Write a message..." />
  <InputGroupAddon align="block-end">
    <InputGroupButton size="sm">Send</InputGroupButton>
  </InputGroupAddon>
</InputGroup>

// Input with loading state
<InputGroup>
  <InputGroupInput placeholder="Searching..." />
  <InputGroupAddon align="inline-end">
    <Spinner />
  </InputGroupAddon>
</InputGroup>

// Input with keyboard shortcut
<InputGroup>
  <InputGroupInput placeholder="Search..." />
  <InputGroupAddon align="inline-end">
    <Kbd>⌘K</Kbd>
  </InputGroupAddon>
</InputGroup>
```

## Examples

### Icon

<ComponentPreview name="input-group-icon-demo" />

### Text

Display additional text information alongside inputs.

`InputGroupText` owns its standard typography and subtle text color. The text example uses associated static message guidance, not a remaining-character count, and does not impose a character limit. Use the component's addon/input spacing rather than local input padding overrides.

<ComponentPreview name="input-group-text-demo" />

### Button

Add buttons to perform actions within the input group.

<ComponentPreview name="input-group-button-demo" />

### Information popovers

Information controls open accessible popovers by keyboard or touch, with optional hover access. Give each popup
a title and description. Keep essential password requirements visible and associated with the input even while
the popup is closed; this example also sets the native eight-character minimum. The email and API-key examples
do not submit or verify credentials.

<ComponentPreview name="input-group-tooltip-demo" />

### Textarea

Input groups also work with textarea components. Use `block-start` or `block-end` for alignment.

The textarea example edits a local draft. Reset restores its sample, and Copy copies the current value without
submitting an enclosing form. Copy failures remain visible without discarding the draft; it does not execute code.

<ComponentPreview name="input-group-textarea-demo" />

### Spinner

Show loading indicators while processing input.

<ComponentPreview name="input-group-spinner-demo" />

### Label

Add labels within input groups to improve accessibility.

<ComponentPreview name="input-group-label-demo" />

### Dropdown

Pair input groups with dropdown menus for complex interactions.

<ComponentPreview name="input-group-dropdown-demo" />

### Button Group

Wrap input groups with button groups to create prefixes and suffixes.

<ComponentPreview name="input-group-button-group-demo" />

### Custom Input

Custom controls that render a native `input` or `textarea` element get group focus state handling automatically. Add a `data-slot` attribute and `aria-invalid` to opt in to the group error state styling.

No style is applied to the custom input. Apply your own styles using the `className` prop.

```tsx
'use client';

import TextareaAutosize from 'react-textarea-autosize';

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

export function InputGroupCustom() {
  return (
    <div className="grid w-full max-w-sm gap-6">
      <InputGroup>
        <TextareaAutosize
          data-slot="input-group-control"
          className="flex field-sizing-content min-h-16 w-full resize-none rounded-md bg-transparent px-3 py-2.5 text-base transition-[color,box-shadow] outline-none md:text-sm"
          placeholder="Autoresize textarea..."
        />
        <InputGroupAddon align="block-end">
          <InputGroupButton className="ml-auto" size="sm">
            Submit
          </InputGroupButton>
        </InputGroupAddon>
      </InputGroup>
    </div>
  );
}
```

```tsx lineNumbers
import { InputGroup, InputGroupAddon } from '@/component/ui/input-group';
import TextareaAutosize from 'react-textarea-autosize';

export function InputGroupCustom() {
  return (
    <InputGroup>
      <TextareaAutosize
        data-slot="input-group-control"
        className="flex field-sizing-content min-h-16 w-full resize-none rounded-md bg-input-fill px-3 py-2 text-base transition-[color,box-shadow] outline-none motion-reduce:transition-none"
        placeholder="Autoresize textarea..."
      />
      <InputGroupAddon align="block-end">how</InputGroupAddon>
    </InputGroup>
  );
}
```

## API Reference

### InputGroup

The main component that wraps inputs and addons.

| Prop        | Type     | Default |
| ----------- | -------- | ------- |
| `className` | `string` |         |

```tsx
<InputGroup>
  <InputGroupInput />
  <InputGroupAddon />
</InputGroup>
```

### InputGroupAddon

Displays icons, text, buttons, or other content alongside inputs.

:::info[Focus Navigation]
For proper focus navigation, the `InputGroupAddon` component should be placed
after the input. Set the `align` prop to position the addon.
:::

| Prop        | Type                                                             | Default          |
| ----------- | ---------------------------------------------------------------- | ---------------- |
| `separator` | `boolean` (block alignments only)                                | `false`          |
| `align`     | `"inline-start" \| "inline-end" \| "block-start" \| "block-end"` | `"inline-start"` |
| `className` | `string`                                                         |                  |

```tsx
<InputGroupAddon align="inline-end">
  <SearchIcon />
</InputGroupAddon>
```

**For `<InputGroupInput />`, use the `inline-start` or `inline-end` alignment. For `<InputGroupTextarea />`, use the `block-start` or `block-end` alignment.**

The `InputGroupAddon` component can have multiple `InputGroupButton` components and icons.

```tsx
<InputGroupAddon>
  <InputGroupButton>Button</InputGroupButton>
  <InputGroupButton>Button</InputGroupButton>
</InputGroupAddon>
```

### InputGroupButton

Displays buttons within input groups.

| Prop        | Type                                                                          | Default     |
| ----------- | ----------------------------------------------------------------------------- | ----------- |
| `shape`     | `"default" \| "pill"`                                                         | `"default"` |
| `size`      | `"xs" \| "icon-xs" \| "sm" \| "icon-sm"`                                      | `"xs"`      |
| `variant`   | `"default" \| "destructive" \| "outline" \| "secondary" \| "ghost" \| "link"` | `"ghost"`   |
| `className` | `string`                                                                      |             |

```tsx
<InputGroupButton>Button</InputGroupButton>
<InputGroupButton size="icon-xs" aria-label="Copy">
  <CopyIcon />
</InputGroupButton>
```

### InputGroupInput

Replacement for `<Input />` when building input groups. This component has the input group styles pre-applied, and the surrounding `<InputGroup />` handles its focus state automatically.

| Prop        | Type     | Default |
| ----------- | -------- | ------- |
| `className` | `string` |         |

All other props are passed through to the underlying `<Input />` component.

```tsx
<InputGroup>
  <InputGroupInput placeholder="Enter text..." />
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
</InputGroup>
```

### InputGroupTextarea

Replacement for `<Textarea />` when building input groups. This component has the textarea group styles pre-applied, and the surrounding `<InputGroup />` handles its focus state automatically.

| Prop        | Type     | Default |
| ----------- | -------- | ------- |
| `className` | `string` |         |

All other props are passed through to the underlying `<Textarea />` component.

```tsx
<InputGroup>
  <InputGroupTextarea placeholder="Enter message..." />
  <InputGroupAddon align="block-end">
    <InputGroupButton>Send</InputGroupButton>
  </InputGroupAddon>
</InputGroup>
```

## Props

<div className="flex flex-row gap-x-3">
  <ExternalLink href="https://ui.shadcn.com/docs/components/input-group" text="Docs" />
</div>

## Credits

- We take our inspiration from [Shadcn UI](https://ui.shadcn.com/docs/components/input-group) for the `input-group` component and style.
