GitHub

Input

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.

beta
tsx
import { Input } from "@idinstudio/ui";

Preview

Real, interactive examples rendered from the live component.

Email must contain an @ symbol.

tsx
<Label htmlFor="email">Email</Label>
<Input id="email" purpose="email" placeholder="you@company.com" />

<Input purpose="email" invalid aria-describedby="email-error" />

Props

Every styling and behavioural attribute is a typed prop — no className at the usage site.

PropTypeDefaultDescription
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.
invalidbooleanfalseRenders the error border and sets aria-invalid="true".
disabledbooleanfalseSets the native disabled attribute and data-state="disabled".
requiredbooleanfalseNative required — screen readers announce "required". Inherited from input attributes.
placeholderstringExample of valid input, not an instruction. Inherited from input attributes.
aria-describedbystringLinks helper text and error messages to the input by id.
refReact.Ref<HTMLInputElement>Forwarded to the underlying input (React 19 ref-as-prop).

Guidelines

When to reach for this component, and when not to.

Do

  • 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

  • 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.


Accessibility

The component's a11y contract. WCAG 2.1 AA is the non-negotiable baseline.

Keyboard

KeyAction
TabMove focus onto the input.
TypingNative text entry.
EnterSubmit the containing form (native).

ARIA & screen reader

Contract
  • Renders a native <input>; implicit role follows the resolved type (textbox, searchbox, spinbutton).
  • invalid renders aria-invalid="true" and data-state="error"; absence is treated as valid.
  • Associate a <Label> via htmlFor + matching id so the field announces with its name.
  • Link helper text and errors through aria-describedby; place errors in a live region (role="alert" or aria-live="polite").
  • purpose drives enterKeyHint and inputMode, so mobile keyboards show the right layout and submit-key label.
  • An unlabeled input must supply aria-label.