Unified UI

Input Group

A composed input field with prefix/suffix icons, left/right text addons, and inline action buttons. Fully styled and size-consistent with the Input component.

Basic

A composed input with prefix/suffix icon slots and left/right text addons. Maintains consistent height with Input, Select, and Button.

https://
USD

Installation

Install the component via the CLI in one command.

npx @work-rjkashyap/unified-ui add input-group
pnpm dlx @work-rjkashyap/unified-ui add input-group
npx @work-rjkashyap/unified-ui add input-group
bunx @work-rjkashyap/unified-ui add input-group

If you haven't initialized your project yet, run npx @work-rjkashyap/unified-ui init first. See the CLI docs for details.

Or install the full package

Use this approach if you prefer to install the entire design system as a dependency instead of copying individual components.

npm install @work-rjkashyap/unified-ui
pnpm add @work-rjkashyap/unified-ui
yarn add @work-rjkashyap/unified-ui
bun add @work-rjkashyap/unified-ui

Anatomy

import { InputGroup, Button } from "@work-rjkashyap/unified-ui";

Basic Usage

InputGroup wraps a standard <input> with optional leading/trailing content. Pass native input attributes via inputProps.

<InputGroup
	prefix={<Search className="size-4" />}
	inputProps={{ placeholder: "Search...", type: "search" }}
/>

Prefix & Suffix Icons

Use prefix and suffix for inline icon slots. These sit inside the input border without a divider.

Left & Right Addons

Addons render outside the text field with a distinct background and a dividing border. Use them for units, labels, or fixed text like http://.

https://
USD
+1
From
To

Combined: Icon + Addon

Mix icon prefixes/suffixes with addons for rich composed inputs.

.com
$
per month
USD

Sizes

SizeHeightUse Case
sm32pxCompact toolbars, dense tables
md36pxDefault — most form contexts
lg40pxProminent inputs, hero forms

Variants

Error State

https://

Disabled

<InputGroup
	disabled
	prefix={<Lock className="size-4" />}
	inputProps={{
		placeholder: "Disabled field",
		defaultValue: "read-only value",
	}}
/>

Inline Action Button

Pass a Button (or any element) as children to replace the default <input> slot with a fully custom layout. This is useful for search bars with an attached submit button.

<InputGroup addonLeft="Search">
	<input
		className="flex-1 h-full bg-transparent outline-none text-sm px-3 text-foreground placeholder:text-muted-foreground"
		placeholder="Type to search..."
	/>
	<Button variant="primary" size="sm" className="m-1 shrink-0">
		Go
	</Button>
</InputGroup>

Custom Children Slot

When children is provided, it replaces the built-in <input>. Use this to compose any input-like element (e.g., a Select, Combobox, or custom control) inside the group's styled container.

<InputGroup addonLeft="Country" addonRight={<Globe className="size-4" />}>
	<select className="flex-1 h-full bg-transparent outline-none text-sm px-3 text-foreground">
		<option>United States</option>
		<option>United Kingdom</option>
		<option>Germany</option>
	</select>
</InputGroup>

Props

PropTypeDefaultDescription
size"sm" | "md" | "lg""md"Height variant — aligns with Button and Input sizes.
variant"default" | "filled""default"Visual style — bordered or muted-filled background.
prefixReactNodeIcon or content rendered inside the input on the left (no border).
suffixReactNodeIcon or content rendered inside the input on the right (no border).
addonLeftReactNodeText or element attached to the left with a distinct background.
addonRightReactNodeText or element attached to the right with a distinct background.
disabledbooleanfalseDisables pointer events and reduces opacity for the whole group.
errorbooleanfalseApplies danger-colored border and focus ring.
inputPropsInputHTMLAttributes<HTMLInputElement>Props spread onto the internal <input> element.
inputClassNamestringAdditional CSS classes applied only to the inner <input>.
childrenReactNodeReplaces the default <input> with a custom element.
classNamestringAdditional CSS classes on the container element.

Accessibility

  • The internal <input> is a native HTML element — all standard accessibility features apply.
  • Use inputProps={{ "aria-label": "..." }} when no visible <label> accompanies the group.
  • Addon text (addonLeft, addonRight) is decorative — it is not programmatically associated with the input. Use aria-label or a visible label to describe the full field.
  • The disabled prop applies pointer-events-none and opacity-50 on the whole group via the CSS has-[:disabled] selector — no JS required.
  • Focus ring appears on focus-within using the standard --ring token.

Design Tokens

TokenUsage
--inputContainer border (default variant)
--mutedAddon background + filled variant
--borderAddon divider border
--ringFocus ring
--dangerError state border and ring
--radius-mdContainer border radius
--duration-fastTransition speed

On this page