Skip to content
Forms

Input Group

An input and its addons inside one border. The group takes the frame and the focus ring; the input inside gives up both, so a currency symbol or a domain suffix sits inside the field rather than beside it.

$
USD

Import

import {
  InputGroup,
  InputGroupPrefix,
  InputGroupSuffix,
} from "@mikenotthepope/substrateui"

Composition

Both addons are optional. The group draws the border and, on focus-within, the ring — so the whole assembly lights up when the input inside it is focused, instead of a ring appearing around only the middle third.

InputGroup
├── InputGroupPrefix
├── Input
└── InputGroupSuffix

An icon on one side

A prefix takes any node, so an icon works as readily as text. Mark it aria-hidden: it repeats what the label and placeholder already say, and an announced "magnifying glass" in front of a search field is noise.

Inside a Field

The group is only a frame — it does no labelling. Put it inside Field and the label, hint, and error wiring work exactly as they do around a bare input.

.substrateui.dev

Lowercase letters, numbers, and hyphens.

Direction

Prefix and suffix are named for reading order, not for sides. Their padding uses ps-3 and pe-3, so in RTL the prefix moves to the right of the field and keeps its inner padding — nothing to configure.

What does not flip is the content you put in them. A currency symbol or a domain suffix is text and belongs where the locale puts it; an arrow or chevron is directional and needs rtl:-scale-x-100. See Direction (RTL).

Accessibility

An addon is a div— decoration, not a label. If the prefix carries information the user needs, say it in the label or the hint too: "Amount in US dollars" rather than relying on a $a screen reader may read as "dollar sign" in the middle of the field's name, or may not reach at all.

The addons are not click targets and do not focus the input. Where an addon should do something — a unit picker, a reveal toggle — put a real button inside it, and remember that button is its own tab stop before or after the field.

The focus ring is drawn by the group with an offset, so it clears the border rather than sitting on it.

API Reference

None of the three parts defines a prop of its own; everything, including className, goes to the underlying div. See React.HTMLAttributes<HTMLDivElement> for that surface — the composition tree above is the more useful map.

PropTypeDefaultDescription
childrenReact.ReactNodeA prefix, an Input, a suffix — in that order. The group strips the nested input's own border and focus ring so the frame is drawn once, by the group.