Input
A single-line text field that owns its label, its error message, and its busyness. Text-like types only.
Types
Seven text-like types cover what a single line of text can be. number is superseded by number-field, which formats and parses in the reader's locale, clamps to its bounds, steps from the keyboard and from its own spin buttons, and reports a number rather than a string. Reach for it whenever the value is a quantity; number here stays for a numeric string nothing does arithmetic on.
className styles the wrapper
Input renders a wrapper around the <input> so it can hold the label and the error message. className styles that wrapper, not the field. Every other native prop passes through to the <input>. Stock shadcn puts className on the field itself, so a copied snippet lands somewhere else than you expect. Every example on this page sets w-64 on the wrapper.
Sizes
Two sizes match the button size tiers, so a field and its submit button line up in a row. There is no variant prop — one look.
End adornment
The endAdornment slot sits inside the border on the right, and the field padding grows so text never runs under it. Pass a plain icon with aria-hidden to describe the field, or a ghost icon button to act on it. There is no leading slot.
Error
Pass error and the field owns the whole failure: the border, the ring, and the label turn destructive, and the message renders below. The field grows downward only, never sideways. There is no shake — the mood is soft, so errors arrive calmly.
Enter a valid email address
Enter a valid email address
Enter a valid email address
Enter a valid email address
Loading
loading puts the spinner in the end slot, replacing any endAdornment. The field stays editable. Input loading means background work — async validation, a search — and the submit button is what locks a flow. With an error alongside it, both show and the spinner turns destructive too: hiding the message during a re-check would flash a validity the field has not earned.
That name is already taken
That name is already taken
Disabled and read-only
Disabled dims the field and its label together and takes no pointer events. Read-only keeps full text contrast on a muted background, takes a normal cursor, and stays focusable so the value can still be read and copied.
Motion
Hover border, focus ring, and the destructive color changes are CSS transitions at --motion-fast. The error message is the one enter and exit: height and opacity on spring-settle both ways at --motion-base, because a bounce on a height change makes the fields below overshoot. The spinner runs its own 800ms turn.
Accessibility
Input generates the field id and wires the label htmlFor itself, so clicking the label focuses the field. An error sets aria-invalid and links the message through aria-describedby, keeping any description you passed. A loading field sets aria-busy and hides its spinner from screen readers, so the wait is announced once. Tab reaches the field first and an interactive adornment second. required marks the label and reaches the <input>; the validation itself stays with your app.