Components

The system's text input — a thin, token-styled wrapper over Base UI's Input. Sharp-cornered, with the shared navy focus ring, and a destructive treatment that turns on automatically inside an invalid Field. Wrap it in a Field for a label, description, and error text.

Install

npx shadcn@latest add @alix/input

Preview

Usage

<Field label="Engagement name">
  <Input placeholder="e.g. Project Atlas" />
</Field>

Examples

01

Native input props

Input forwards the native control API, so type, defaultValue, disabled, and placeholder stay at the call site.

<Input type="email" defaultValue="amelia.ward@example.com" />
<Input placeholder="Client code" disabled />
02

Invalid state from field

Field owns the error text and flips the Input into its destructive treatment through aria-invalid.

Enter a client-facing name.

<Field label="Engagement name" error="Enter a client-facing name.">
  <Input placeholder="e.g. Project Atlas" />
</Field>
03

Form row with owner

Use Field, Input, Select, and Button together when a short form needs accessible labels and one clear action.

<div className="grid gap-4 md:grid-cols-[1fr_14rem_auto] md:items-end">
  <Field label="Engagement name">
    <Input defaultValue="Project Atlas" />
  </Field>
  <Field label="Owner">
    <Select
      defaultValue="jp"
      items={[
        { value: "jp", label: "J. Patel" },
        { value: "rs", label: "R. Silva" },
      ]}
    />
  </Field>
  <Button>Save</Button>
</div>

When to use it

Use it for

  • Single-line text, email, search, number, and short identifier fields.
  • Bare controls only inside an already-labelled context such as a filter toolbar.
  • Field-wrapped form rows when the control needs label, helper, required, or error wiring.

Reach for something else

  • Multi-line notes, summaries, or comments — use Textarea instead.
  • Prefix, suffix, icon, or inline-button shells — use InputGroup instead.
  • Finite option sets where free text is not allowed — use Select instead.

Props

PropTypeDefaultDescription
placeholderstringGhost text shown while empty, in the muted-foreground colour.
onValueChange(value: string) => voidBase UI's value callback, forwarded alongside every native input prop (value, defaultValue, type, disabled, …).
classNamestringMerged onto the control — the wrapper only adds styling, it never owns the input's API.

See also