Input

Takes one line of text.

Mode

  • textdefault

  • password

  • search

  • copy

Sizes

  • sm

  • defaultdefault

  • lg

States

  • rest

  • hover

  • focus

  • filled

  • invalid

  • disabled

  • read-only

Usage

When to use it
Use
The answer fits on one line: a name, an email, a URL, a bucket path, a limit.
Use
The person filters a list already on the page (mode="search").
Use
The person reads a value to paste elsewhere, like an endpoint or a connection string (mode="copy").
Not for
The answer runs to more than one line, like a query or a note. Use Textarea.
Not for
The value is one of a known list. Use Select.
Not for
The value is on or off and applies at once. Use Switch.

Rules

10 rules
Must
Put an Input in a Field with a FieldLabel, or give it aria-label when a visible label sits elsewhere. Because a placeholder vanishes on the first keystroke and is not a reliable accessible name.
Must
Pass an icon, a scheme, a unit or a button as leading or trailing, never beside the Input. Because outside the edge it sits outside the line that turns gold on focus, and a press on it does not put the cursor in the text.
Must
Use InputAction for a button inside the field; it is a cell of the field, its full height and flush with the edge. Because a plain Button keeps its own height and edge, so it floats inside the field with a double line beside it.
Must
Give a primary InputAction only to a field that is a whole one-line form, with no other slab beside it. Because the slab at the field's end is the group's one action, and a second one next to it splits the eye.
Never
Draw a ring, an outline or a shadow on an Input to show focus. Because the field draws its own focus, a white body with the gold edge doubled inward and a 1px pale yellow halo, and a second ring outside it reads as another box.
Never
Set an Input's height, corners, text size or side padding in className; pass size. Because corners are square, a fixed height clips at 200% zoom, and the size sets the inset so the nearest thing you see sits as far from the side as from the top: text 10px in at 32px, a glyph 7px, a key cap 5px, measured.
Must
Set mono on a field that holds an ID, a key, a path or a command; leave names and emails in the sans. Because mono keeps every character the same width, so 0 and O, l and 1 are told apart, while a name in mono reads as code.
Must
Use mode="search" for a search box, never an icon placed over an input. Because a hand-placed icon misses the clear button, Escape to clear, the pending mark and the key hint.
Must
Give shortcut to one search per page; pass shortcutOwner={false} on another that only shows the hint. Because only the first claiming field in document order gets the key, so a second claim does nothing.
Should
Set type and autoComplete on an email, a URL or a phone number. Because without type a phone shows the text keyboard and autofill cannot offer the address.

State order

6 states, highest first
1
disabled
2
invalid
3
focus
4
read-only
5
hover
6
rest

Accessibility

6 checks
The control is a native textbox named by FieldLabel or aria-label, with aria-invalid and aria-describedby from the Field.
The edge is --line, the rule colour, 1.3:1 on the page, so the label, the placeholder and the off-white fill identify the field; focus turns it --focus at 2px, 6.2:1 in light and 12.9:1 in dark, with a pale halo outside, and forced colours draw a Highlight outline.
Invalid adds the error sentence under the field, so it never rests on the red edge alone.
The password toggle sets aria-pressed and names itself Show or Hide; its glyph changes with it.
Escape in a search clears the query; a second Escape leaves the field. The key hint is aria-hidden.
Text is 16px under a coarse pointer, so a phone browser never zooms the page on focus.

Keyboard

3 keys
Escape
In a search, clears the query; with no query, leaves the field.
/ (or the shortcut)
Focuses the search that owns it, from anywhere outside a field, dialog or menu.
Enter
Submits the form around it.

Edge cases

6 edge cases
Long value
Scrolls inside the field; a copy value truncates and still copies all of it.
Narrow row, 160px
The text shrinks before any slot; slots and actions keep their size.
Right to left
Leading and trailing swap sides; a scheme like https:// keeps its own order.
Zoom 200%
The field grows with the text past its token, and its action cells grow with it.
Slow search
The magnifier turns into the pending mark in the same width, so the text never moves.
Disabled Field or FieldSet
The text, the slots and every action inside go quiet together.

API

10 props
mode
'text' | 'password' | 'search' | 'copy' default 'text'
size
'sm' | 'default' | 'lg' default 'default'
leading, trailing
ReactNode
mono
boolean default false
aria-invalid
boolean
className, controlClassName
string
defaultRevealed
boolean default false
shortcut, shortcutOwner, pending, clearLabel
string, boolean, boolean, string default , true, false, 'Clear search'
value, noun, onCopy
string, string, (v) => void
InputAction size, variant
'icon' | 'text', 'ghost' | 'primary' default 'icon', 'ghost'

Tokens

32 tokens
--field-bg
#f8f7f3
--field-hover
#fefefd
--field-edge
var(--line)
--field-edge-hover
#ecebe5
--field-ring-hover
#f4f3ee
--field-focus-bg
#ffffff
--field-ring-focus
#fff1b8
--field-ring-fail
#fbdcd8
--field-inset-sm
7px
--field-inset
10px
--field-inset-lg
11px
--well
#f4f3ee
--focus
#7a5d00
--fail
#b3261e
--text-1
#161512
--text-2
#55524a
--text-3
#6b675e
--text-disabled
#a8a499
--control-sm
26px
--control
32px
--control-lg
36px
--line-width
1px
--type-body-sm
400 14px/20px var(--font-sans)
--type-caption
400 13px/18px var(--font-sans)
--type-body
400 15px/24px var(--font-sans)
--type-code
400 13px/20px var(--font-mono)
--type-code-sm
400 12px/16px var(--font-mono)
--icon
16px
--icon-sm
14px
--pending-cell
3px
--dur-light
240ms
--ease-soft
cubic-bezier(0.22, 0.8, 0.24, 1)

Install

For your coding agent

GitHub

Please star me pookie

198

A new design system every week

Leave your email before you copy the prompt.