A single-line text input. The purpose prop auto-configures the native HTML attributes — type, autoComplete, inputMode, enterKeyHint and more — from a canonical map, so password managers, autofill, and the correct mobile keyboard all work without manual wiring. Always pair Input with a Label.
import { Input } from "@idinstudio/ui";Real, interactive examples rendered from the live component.
Email must contain an @ symbol.
<Label htmlFor="email">Email</Label>
<Input id="email" purpose="email" placeholder="you@company.com" />
<Input purpose="email" invalid aria-describedby="email-error" />Every styling and behavioural attribute is a typed prop — no className at the usage site.
| Prop | Type | Default | Description |
|---|---|---|---|
purpose | "email" | "password-current" | "tel" | "url" | "search" | "otp" | … | — | Canonical purpose. Auto-sets type, autoComplete, inputMode, enterKeyHint, spellCheck, pattern and more. Consumers never wire those attributes by hand. |
size | "sm" | "md" | "lg" | "md" | Control height and text size. md is the default form-field height. |
invalid | boolean | false | Renders the error border and sets aria-invalid="true". |
disabled | boolean | false | Sets the native disabled attribute and data-state="disabled". |
required | boolean | false | Native required — screen readers announce "required". Inherited from input attributes. |
placeholder | string | — | Example of valid input, not an instruction. Inherited from input attributes. |
aria-describedby | string | — | Links helper text and error messages to the input by id. |
ref | React.Ref<HTMLInputElement> | — | Forwarded to the underlying input (React 19 ref-as-prop). |
When to reach for this component, and when not to.
Always pair an Input with a <Label> via htmlFor and a matching id.
Set purpose so autofill, password managers, and the right mobile keyboard work.
Use placeholder for an example value ("you@company.com"), not an instruction.
On error, set invalid and connect the message with aria-describedby.
Don't set type, autoComplete or inputMode by hand — use purpose.
Don't rely on placeholder as the field label; it disappears on input.
Don't add a purpose that isn't in the map — extend purpose-map.ts via a Changeset.
Don't leave an input unlabeled without an aria-label.
The component's a11y contract. WCAG 2.1 AA is the non-negotiable baseline.
| Key | Action |
|---|---|
| Tab | Move focus onto the input. |
| Typing | Native text entry. |
| Enter | Submit the containing form (native). |