Input Group

An input with prefix and suffix addons.

Usage

The group draws the border and the focus ring; the input inside draws neither. That inversion is the whole component — an addon placed next to a bordered input is two boxes touching, and no amount of spacing makes them read as one control.

The addon's side comes from where you put it. There is no side prop, because DOM order already says it and a prop that could disagree with the layout is a prop that will.

Prefix and suffix

With a button

Put a Button where an addon would go. :focus-within keeps the ring around the whole group, so focusing the button does not make it look like it fell outside the field.

An addon is not a label

Addon is aria-hidden by default, and that default is right more often than it looks. A magnifier, a $, a https:// — these are hints for the eye. The meaning has to live in the input's own accessible name, because an addon cannot become one.

decorative=false puts an addon back in the accessibility tree. Use it only when the text is the sole place the information exists — and fix the input's name anyway.

Invalid

Pass invalid to both: the group so the border and ring turn, the input so aria-invalid is set. Styling alone tells sighted users and nobody else.

Props

Each part also takes its native element's attributes via prop spreading.

PropTypeDefault
size Match the size of the `Input` inside.'sm' | 'md' | 'lg''md'
invalid Mark the whole group invalid, alongside the input's own `invalid`.booleanfalse
class Extra classes merged onto the root element.string
children required Snippet
PropTypeDefault
decorative Whether this addon is decoration. Default `true`, which hides it from the accessibility tree. That default is right far more often than it looks. A magnifier icon, a `$`, a `https://` — these are hints for the eye, and the input's own label is what has to carry the meaning ("Amount in dollars", not "Amount" beside a `$` nobody hears). Set `decorative={false}` only when the text is the ONLY place the information exists, and then make sure the input's accessible name still makes sense on its own — an addon is not a label and cannot become one.booleantrue
class Extra classes merged onto the element.string
children required Snippet