Input Group

Joins several controls, a field, a Select, a static affix, a small icon-only action, into one seamless segmented shell. The group owns the border and focus ring; each segment goes chromeless and melts in.

$

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Add this component (its dependencies come along)npx koalaui-cli@latest add input-group

Usage#

usage.tsxTSX
import { InputGroup, InputGroupAddon } from "@/components/ui/input-group"import { InputRoot, InputField } from "@/components/ui/input"export function Example() {  return (    <InputGroup>      <InputGroupAddon>https://</InputGroupAddon>      <InputRoot>        <InputField placeholder="yourcompany" />      </InputRoot>      <InputGroupAddon>.com</InputGroupAddon>    </InputGroup>  )}

Anatomy#

import { InputGroup, InputGroupAddon } from "@/components/ui/input-group"import { InputRoot, InputField } from "@/components/ui/input"<InputGroup>  <InputGroupAddon />  <InputRoot>    <InputField />  </InputRoot></InputGroup>

When to reach for it#

An Input already handles adornments inside a single field - a leading icon (InputPrefix), a divided label (InputPrefixLabel), a trailing icon button (InputSuffixButton). Reach for InputGroup only when you need to join several distinct controls - a Select, another field, a static affix - into one unit. One shell, one focus ring, one set of rounded corners.

A prominent text action - Subscribe, Invite, Search - does not belong inside the shell. Crammed in, it reads as a button trapped in a field. Keep it a detached Button beside the group instead (see below). Only a small icon-only action may melt in.

Pairing with an action#

Do not fuse a big text button into the field. Drop the group (or a plain InputRoot) and the Button into one flex row (items-stretch gap-2) at the same size: the field flexes, the button caps the row from outside, and the heights line up on their own. It reads as a real button, not a segment. Make that row the <form> so the button takes the field's corner.

With a Select#

Drop a real Select in as a segment and it melts into the shell - its own border, ring, and background are stripped while its menu, keyboard nav, and ARIA stay intact. The field flexes to fill the row. The Invite action, being a text button, stays detached beside the group - same rule as the newsletter, one step richer.

Text affixes#

InputGroupAddon is a static, non-interactive segment for a unit, protocol, or symbol. It shares the shell background and reads as a muted label, on either side of the field.

https://
.com
@

Icon-only actions can melt in#

The one action that may live inside the shell is a small icon-only button - copy, clear, a submit arrow. With no label to crowd the field, it sits flush as a fused segment: it keeps its fill and hover but drops its own radius and ring. Use iconOnly and give it an aria-label.

koala.dev/

Sizes#

The size prop sets the shell height (sm 32, md 36, lg 40px) and the affix scale, and imposes it on the inner controls. Give the detached Button the matching size so every part lines up.

States#

hasError paints the whole shell red and turns the focus ring destructive; disabled dims and locks the row. Inside a Field, both cascade automatically. For form semantics, also disable the inner control so it is excluded from submission.

@
https://
.com

API reference#

InputGroup

The shell that joins several controls into one bordered row, role="group". Renders a <div> and forwards all its props. Every part accepts className, merged last.

PropTypeDefaultDescription
size"sm" | "md" | "lg"-Shell height (32, 36 or 40px), imposed on every segment inside. Unset, it comes from a container (Form imposes lg) or density (compact, the default, is sm; comfortable is md).
density"comfortable" | "compact"-Only picks the default size (compact is sm, comfortable is md). An explicit size wins.
hasErrorboolean-Destructive border and ring. Inherited from a surrounding Field when unset.
disabledboolean-Dims and locks the shell. Inherited from a surrounding Field; also disable the inner control for form semantics.
Data attributeDescription
data-control-sizeThe resolved size: sm, md or lg.
data-disabledPresent when the group is disabled.
data-errorPresent when the group is in the error state.

InputGroupAddon

A static affix segment (https://, $, .com, an icon) in the shell's muted ink. Renders a <span> and forwards all its props.

FAQ#

Input already covers adornments inside one field: a leading icon (InputPrefix), a divided label (InputPrefixLabel), a trailing icon button (InputSuffixButton). Use InputGroup only when you are joining several distinct controls - a Select, another field, a static affix - into one shell. If everything lives in a single field, you do not need InputGroup.