Input Group
Single bordered shell combining an input with leading or trailing addons, text, and buttons.
Installation
The components are exported from @by/experience-system. Add the package with your package manager:
pnpm add @by/experience-systemIn this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.
Composition
Use the following composition to build an InputGroup:
InputGroup
├── InputGroupAddon (optional, repeat)
│ ├── InputGroupText (optional)
│ └── InputGroupButton (optional)
├── InputGroupInput
└── InputGroupAddon (optional)InputGroupInput (or a SelectTrigger wired like a group control) should carry data-slot="input-group-control" so the shell applies focus and invalid styles. Addons use align for block/inline placement.
Usage
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
InputGroupText,
} from '@by/experience-system';InputGroup and its parts are client components ('use client'). Use them inside a Client Component or a dynamic import when using the Next.js App Router.
<InputGroup>
<InputGroupAddon>
<InputGroupText>https://</InputGroupText>
</InputGroupAddon>
<InputGroupInput placeholder="example.com" />
</InputGroup>Examples
Overview
Trailing icon addon and leading URL prefix with a tooltip help InputGroupButton.
With icons
Leading and trailing icon addons.
With buttons
Copy, popover, and outline action buttons in addons.
With tooltips
Help buttons inside trailing addons.
Filled appearance
appearance="filled" on the shell to match Input filled.
Sizes
sm, md, and lg shells with aligned addon typography.
API Reference
Subsection titles name the exports from @by/experience-system. InputGroupInput forwards to Input; see the Input page for control props (size, appearance, readOnly, aria-invalid, …). The shell mirrors the shared field-control surface with the group context.
InputGroup
| Prop | Type | Default |
|---|---|---|
appearance | default | filled | default |
size | sm | md | lg | md |
| Data attribute | Values |
|---|---|
data-slot | input-group |
data-appearance | mirrors appearance |
data-size | mirrors size |
data-disabled | present when an inner control reports disabled |
Renders role="group". Also accepts standard div attributes.
InputGroupAddon
| Prop | Type | Default |
|---|---|---|
align | inline-start | inline-end | block-start | block-end | inline-start |
groupSize | sm | md | lg | from context |
| Data attribute | Values |
|---|---|
data-slot | input-group-addon |
data-align | mirrors align |
Clicking the addon focuses the nested input unless the event target is a button. Also accepts standard div attributes.
InputGroupButton
Button with group-aware sizing defaults. size overrides the mapped default from group size.
Also accepts Button props (excluding the internal size resolution when omitted).
InputGroupText
Muted inline text sized from group size.
Also accepts standard span attributes.
InputGroupInput
Forwards to Input; size and appearance default from InputGroup when omitted. Merges classes for borderless group layout.
| Data attribute | Values |
|---|---|
data-slot | input-group-control |
Also accepts Input props.
Accessibility
Keep a single tab stop in the text field unless addons expose real controls (button, a). Provide aria-label or visible text for icon-only InputGroupButton elements. Surface validation with aria-invalid on InputGroupInput so addon text color follows the invalid state. See MDN — input.
Keyboard interactions
| Key | Description |
|---|---|
Tab | Moves focus through inputs and interactive addons. |
Space / Enter | Activates InputGroupButton controls when focused. |
Source in the repo: packages/experience-system/src/components/InputGroup/InputGroup.tsx. Agent-oriented contracts: packages/experience-system/src/components/InputGroup/InputGroup.instructions.md.