Input

Takes one line of text, like a name, a key, a number or a code.

Examples

A name

Search with a shortcut

Text before and after

https://.helpdesk.example

A key you can copy

Hidden, ending in a1b2

Hides again 30 seconds after you show it.

A limit that steps by its size

Shift moves ten times as far.

A new password

A code from an app

Six digits. Paste works.

Mode

  • textdefault

  • password

  • Hidden, ending in a1b2

    secret

  • copy

  • search

  • number

  • Code

    otp

Sizes

  • sm

  • defaultdefault

  • lg

States

  • rest

  • hover

  • focus-visible

  • invalid

  • disabled

  • read-only

Usage

When to use it
Use
The answer fits on one line: a name, email, URL, ID or amount.
Use
The value is a secret the person pastes or reads once: a widget key, webhook secret or password.
Use
The person filters a list that is already on the page.
Use
A short code arrives by message or from an authenticator app.
Not for
The answer runs to more than one line. Use Textarea.
Not for
The person picks from more than about seven options, or adds several values. Use Combobox.
Not for
The value is a date, a range or a time. Use Date picker.
Not for
The value is on or off and applies at once. Use Switch.
Not for
The search covers the whole product, not this list. Use Command.

Rules

12 rules
Must
Put an Input that takes typed text in a Field with a FieldLabel, not a placeholder or a loose label. Because a placeholder vanishes on the first keystroke and is not a reliable accessible name.
Must
Use mode="secret" for a credential, token or key, never type="password". A masked key keeps its length: one dot per hidden character. Because type="password" hides the tail that tells two keys apart, offers no copy, and invites the password manager to save it.
Must
Pass an icon, scheme, unit or button as prefix or suffix, never beside the Input. Because outside the box the icon sits outside the edge that darkens on hover and turns ink on focus, and a click on it does not focus the text.
Must
Use mode="search" for a search box, never an icon and an input in a relative wrapper. Because a hand-placed icon misses the clear button, Escape to clear and the shortcut hint.
Must
Give shortcut to one search per page; pass shortcutOwner={false} on others to show the hint only. Because only the first claiming field in document order gets the key, so a second claim does nothing.
Should
Set step="auto" on a number that spans more than two orders of magnitude.
Must
Use generate on a password field so the generated value is revealed. Because a value set by hand stays masked with autoComplete="current-password", so the person never sees what to save.
Must
Set type and autoComplete for email, url and tel, or use mode="otp" for a one-time code. Because without type a phone shows the text keyboard and autofill cannot offer the address.
Should
Give the placeholder an example value in the expected format, not the label again.
Should
Pass noun on a secret or copy field so its buttons read "Show widget key" and "Copy widget key".
Never
Add a border or change the text size on an Input. Because the box draws its own edge and its ink focus, and text-xs drops the 16px touch size that stops iOS zoom.
Should
Keep an Input at least 160px wide and stack the row under 320px.

Accessibility

7 checks
The control is a native textbox named by FieldLabel or aria-label, with aria-invalid and aria-describedby from the Field.
Number is a spinbutton with aria-valuetext including the unit; steppers are named with the step and skipped by Tab.
The reveal toggle sets aria-pressed; a hidden secret is described as "Hidden, ending in" the last characters.
OTP slots name the first from the label and the rest "Character n of 6"; a rejected key is announced in a status region.
Escape in a search clears the query; a second Escape leaves the field.
Text is 16px under pointer: coarse so iOS does not zoom; never set a smaller size.
Forced colors draw a 1px system border on the box; the focus edge stays.

Edge cases

11 edge cases
Long value
Scrolls inside the box; copy truncates and still copies all; a read-only secret keeps its start and tail.
Empty copy value
Reads "None" with Copy disabled; an empty read-only secret drops its buttons.
120px wide
Search keeps icon and shortcut; a number shrinks its unit before its digits.
Right to left
Prefix and suffix swap sides; wrap Latin pieces in bdi dir="ltr".
Slow search
The spinner stays in the prefix and the box keeps its size; the caller owns the timeout.
In a well
Stays paper with its control edge, so it reads on the grey.
Letter typed in numeric OTP
Refused and announced as "Digits only".
Number out of range
Clamps when stepped; a typed value clamps on blur.
Stepper pressed ten times
Adds exactly ten steps from the typed number.
Enter inside a form
Submits the form; no button in the field submits it.
Reduced motion
The search spinner stops and stays visible.

API

10 props
mode
'text' | 'password' | 'secret' | 'copy' | 'search' | 'number' | 'otp' default 'text'
size
'sm' | 'default' | 'lg' default 'default'
prefix, suffix
ReactNode
className
string
generate
boolean | () => string
noun, readOnly, redacted, tail
string, boolean, boolean, number default 'value', false, false, 4
value, copyLabel, onCopy
string, string, (v) => void
shortcut, shortcutOwner, pending
string, boolean, boolean default , true, false
min, max, step, unit
number, number, number | 'auto', ReactNode
length, groups, onComplete
number, number[], (v) => void

Tokens

23 tokens
--line-control
oklch(var(--ink-c) / 0.16)
--radius-soft
6px
--text-1
var(--ink)
--type-label
400 14px/16px var(--font-sans)
--control-sm
28px
--control
32px
--control-lg
44px
--line-frame
oklch(var(--ink-c) / var(--line-frame-alpha))
--dur-fast
120ms
--ease-step
cubic-bezier(0.2, 0, 0, 1)
--line-focus
2px
--focus-halo
0 0 0 3px oklch(var(--ink-c) / 0.08)
--border-focus
var(--ink)
--focus-offset
2px
--accent-line
var(--ink)
--accent-mark
var(--ink)
--text-disabled
oklch(var(--ink-c) / 0.40)
--text-3
oklch(var(--ink-c) / 0.66)
--text-2
oklch(var(--ink-c) / 0.80)
--type-code
400 13px/20px var(--font-mono)
--features-data
"tnum", "zero", "ss04"
--type-label-sm
400 12px/16px var(--font-sans)
--type-heading-sm
400 20px/24px var(--font-sans)

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.