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.
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
└── InputGroupSuffixAn 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.
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.
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | A 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. |