Skip to content
Primitives

Input

Single-line field with mono readout text and a 2px signal focus ring.

● LIVE
npx shadcn@latest add https://okibi.cndr.dev/r/input.json

Installation

Install the theme first, then add the component:

npx shadcn@latest add https://okibi.cndr.dev/r/input.json

Install the required dependencies:

npm install class-variance-authority

Copy the source from the Code tab above into components/ui/input.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.

Usage

import { Input } from "@/components/ui/input"

<Input type="email" placeholder="operator@relay" />

Examples

With label

Pair the field with a Label (matching htmlFor/id) so the control is named for assistive tech and the label is a click target.

● LIVE

With button

Sit the field next to a Button in a flex row for inline submit fields — a callsign transmit, a search, an invite.

● LIVE

File

type="file" gets the same keyline and mono treatment as the text field.

● LIVE

Disabled

The native disabled attribute blocks interaction and dims the field.

● LIVE

Invalid

Set aria-invalid to flip the focus ring and border to the destructive color for inline validation errors.

● LIVE

SEC // malformed channel reference.

API Reference

Input

PropTypeDefaultDescription
size"sm" | "default" | "lg""default"Field height, to compose with the Button/Select size scale.
typestring"text"Native input type (email, file, password, …).

Accessibility

  • Renders a native input, so keyboard, autofill, and type-specific UI (date, file, number) all work out of the box.
  • It ships no built-in label — associate a Label via htmlFor/id, or wrap the field, so the control is named.
  • Set aria-invalid to flag an error: the border, a faint fill, and the focus ring all swap to destructive.
  • Focus-visible draws a 2px inset signal ring; disabled drops opacity to 60% and blocks pointer events.
  • There is no built-in error-message slot — render help/error text yourself and wire it with aria-describedby.

Guidelines

Do

  • Pair every field with a Label bound by htmlFor — the placeholder is not a label.
  • Match size to the Button/Select it sits beside (sm / default / lg).
  • Set the right type (email, password, number) so mobile keyboards and validation adapt.
  • Drive errors through aria-invalid and link the message with aria-describedby.

Don't

  • Don't rely on the uppercase placeholder to carry the field's name — it vanishes on input.
  • Don't hand-roll heights via className when a size token exists.
  • Don't use a destructive border for an error without also setting aria-invalid.
  • Don't expect a built-in error slot — the primitive leaves message rendering to you.

On this page