Forms & input
Input
The text field people type into all day — task names, search, emails, amounts, notes. One control handles labels, helper and error text, leading icons, prefixes, counters, and a multi-line mode.
npx shadcn@latest add @orbit/inputPlayground
Anatomy
A field is a vertical stack: an optional label row, the input itself with adornment slots, and a footer for guidance, errors, or a counter.
- 1LabelA persistent field name, with an optional “Optional” tag on the right when a field isn’t required.
- 2Leading slotA muted icon — or inline prefix text — that frames what to type.
- 3Value & placeholderThe text the person enters; placeholder shows an example in muted gray until they do.
- 4FooterHelper text, the in-place error message, and an optional character counter.
Field types
One type prop adapts the keyboard, affordances, and validation hints.
Icons, affixes & actions
Slots on either side of the value: a leading icon, inline prefix/suffix text, a keyboard hint, and trailing actions like clear or reveal.
Sizes
md 34px (default) · sm 30px. Matched to Select and Button so fields line up in any form row.
States
Borders and rings communicate status; helper text becomes the error message in place.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| type | "text" | "search" | "password" | "email" | "url" | "number" | "textarea" | "text" | Field type. “textarea” switches to the multi-line field. |
| size | "sm" | "md" | "md" | Control height: 30 / 34px. |
| label | string | — | Persistent field name above the wrapper, bound with htmlFor. |
| placeholder | string | — | Short example value in muted gray. |
| value / defaultValue | string | — | Controlled value with onChange, or an uncontrolled initial value. |
| helper | string | — | Guidance below the field. |
| errorText | string | — | Message that replaces helper while error is set. |
| iconLeft | ReactNode | — | Muted leading icon (15px md / 14px sm). |
| prefix / suffix | string | — | Inline muted text before / after the value ($, USD, https://, hrs). |
| kbd | string | — | Keyboard-hint chip shown while the field is empty. |
| clearable | boolean | false | Trailing × that resets the value; Esc does the same. |
| counter | boolean | false | Character counter — requires maxLength; warns above 90%. |
| maxLength | number | — | Native maxLength, also drives the counter. |
| rows | number | 3 | Visible rows for type=“textarea”. |
| optional | boolean | false | Muted “Optional” tag on the label row. |
| error | boolean | false | Danger border and message; sets aria-invalid. |
| valid | boolean | false | Trailing success check (single-line, non-password). |
| disabled / readOnly | boolean | false | Native disabled / read-only states. |
| forceState | "none" | "hover" | "focus" | "error" | "none" | Demo aid — pins a visual state. |
| width | string | "280px" | Root width; use “100%” to fill or “auto”. |
| …rest | InputHTMLAttributes | — | Everything else is forwarded to the native <input> / <textarea>, including ref. |
Usage
Always pair a field with a label
Persistent labels beat placeholder-only fields, which vanish the moment typing starts.
Put instructions in the placeholder
Use helper text for guidance; the placeholder is just a short example value.
Show errors in place, on blur
Swap helper text for a specific message and red border next to the field.
Validate on every keystroke
Flagging an email as invalid mid-typing is noisy — wait until the field loses focus.
Keyboard & accessibility
Native <input> / <textarea> semantics. The label is bound with htmlFor, aria-invalid is set on error, and helper or error text is linked via aria-describedby.