input group
Group inputs, in layouts, more easily.
Philosophy
Complex input patterns — search bars, URL fields, currency inputs — need structure beyond a bare <input>. InputGroup composes Input with addons, icons, and buttons in a unified container. Rather than building a mega-input with dozens of props, we give you building blocks that snap together. Composition over configuration.
How It's Built
Installation
npx @gentleduck/cli add input-group
npx @gentleduck/cli add input-group
Usage
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
InputGroupText,
InputGroupTextarea,
} from "@/components/ui/input-group"import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
InputGroupText,
InputGroupTextarea,
} from "@/components/ui/input-group"<InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
<InputGroupAddon align="inline-end">
<InputGroupButton>Search</InputGroupButton>
</InputGroupAddon>
</InputGroup><InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
<InputGroupAddon align="inline-end">
<InputGroupButton>Search</InputGroupButton>
</InputGroupAddon>
</InputGroup>Examples
Icon
Text
Display additional text information alongside inputs.
Button
Add buttons to perform actions within the input group.
Tooltip
Add tooltips to provide additional context or help.
Textarea
Input groups also work with textarea components. Use block-start or block-end for alignment.
Spinner
Show loading indicators while processing input.
Use Button loading inside InputGroupButton for the built-in animated <Loader /> spinner behavior.
Label
Add labels within input groups to improve accessibility.
Dropdown
Pair input groups with dropdown menus for complex interactions.
Button Group
Wrap input groups with button groups to create prefixes and suffixes.
Custom Input
Add the data-slot="input-group-control" attribute to your custom input for automatic behavior and focus state handling.
No style is applied to the custom input. Apply your own styles using the className prop.
import { InputGroup, InputGroupAddon } from "@/components/ui/input-group"
import TextareaAutosize from "react-textarea-autosize"
export function InputGroupCustom() {
return (
<InputGroup>
<TextareaAutosize
data-slot="input-group-control"
className="dark:bg-input/30 flex field-sizing-content min-h-16 w-full resize-none rounded-md bg-transparent px-3 py-2 text-base transition-[color,box-shadow] outline-none"
placeholder="Autoresize textarea..."
/>
<InputGroupAddon align="block-end">how</InputGroupAddon>
</InputGroup>
)
}import { InputGroup, InputGroupAddon } from "@/components/ui/input-group"
import TextareaAutosize from "react-textarea-autosize"
export function InputGroupCustom() {
return (
<InputGroup>
<TextareaAutosize
data-slot="input-group-control"
className="dark:bg-input/30 flex field-sizing-content min-h-16 w-full resize-none rounded-md bg-transparent px-3 py-2 text-base transition-[color,box-shadow] outline-none"
placeholder="Autoresize textarea..."
/>
<InputGroupAddon align="block-end">how</InputGroupAddon>
</InputGroup>
)
}API Reference
InputGroup
The root container that wraps inputs and addons into a unified group with shared border and focus states.
| Prop | Type | Default | Description |
|---|---|---|---|
dir | 'ltr' | 'rtl' | -- | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr'). |
className | string | -- | Additional CSS classes to apply |
children | React.ReactNode | -- | InputGroup sub-components to render inside the group |
...props | React.HTMLProps<HTMLDivElement> | -- | Additional props to spread to the content div |
InputGroupAddon
Displays icons, text, buttons, or other content alongside inputs.
For proper focus navigation, the InputGroupAddon component should be placed
after the input. Set the align prop to position the addon.
| Prop | Type | Default | Description |
|---|---|---|---|
align | 'inline-start' | 'inline-end' | 'block-start' | 'block-end' | 'inline-start' | Position of the addon relative to the input. Use inline-start/inline-end with InputGroupInput and block-start/block-end with InputGroupTextarea. |
className | string | -- | Additional CSS classes to apply |
children | React.ReactNode | -- | Icons, text, buttons, or other content |
...props | React.HTMLProps<HTMLDivElement> | -- | Additional props to spread to the content div |
InputGroupButton
A button styled for use within input groups. Renders a Button with compact sizing defaults.
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'xs' | 'icon-xs' | 'sm' | 'icon-sm' | 'xs' | Size of the button |
variant | 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' | 'dashed' | 'warning' | 'nothing' | 'expand_icon' | 'ghost' | Visual variant of the button |
type | string | 'button' | The HTML button type attribute |
className | string | -- | Additional CSS classes to apply |
...props | Omit<React.ComponentPropsWithoutRef<typeof Button>, 'size'> | -- | Additional props inherited from Button (excluding size). |
InputGroupText
A styled span for displaying static text within input groups.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes to apply |
children | React.ReactNode | -- | Text or icon content to display |
...props | React.HTMLProps<HTMLSpanElement> | -- | Additional props to spread to the span element |
InputGroupInput
Replacement for <Input /> when building input groups. Has input group styles pre-applied and uses the unified data-slot="input-group-control" for focus state handling.
| Prop | Type | Default | Description |
|---|---|---|---|
dir | 'ltr' | 'rtl' | -- | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr'). |
className | string | -- | Additional CSS classes to apply |
...props | React.HTMLProps<HTMLInputElement> | -- | Additional props to spread to the input element |
InputGroupTextarea
Replacement for <Textarea /> when building input groups. Has textarea group styles pre-applied and uses the unified data-slot="input-group-control" for focus state handling.
| Prop | Type | Default | Description |
|---|---|---|---|
dir | 'ltr' | 'rtl' | -- | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr'). |
className | string | -- | Additional CSS classes to apply |
...props | React.HTMLProps<HTMLTextAreaElement> | -- | Additional props to spread to the textarea element |
RTL Support
Direction is resolved through the shared primitives direction module. Use a local dir="rtl" override when the component exposes it, or set DirectionProvider at app/root level for global RTL/LTR behavior.