Input
Text input on the field surface, with a forced-colors-safe focus ring.
Input is a single-line text field for names, email addresses, search terms, and numbers. It
renders a native <input> on bg-surface, fills the width of its container at 40px tall,
and draws a destructive border under aria-invalid. Pair it with
Field for a label, a description, and an error, and use
Input group to put an icon or a short suffix inside
it. Its corners follow the look's rounded, so it is an 8px rectangle in Washi and rounds
to 16px in ICS, where buttons are pills.
Usage
import { Field, FieldLabel } from '@/components/ui/field';
import { Input } from '@/components/ui/input';
<Field>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input id="email" type="email" autoComplete="email" />
</Field>Input takes every <input> attribute and adds no props of its own, so type, name,
value, onChange, autoComplete, and inputMode work as they do on the element, and a
ref reaches the <input>. Its border is the strong border at border-stroke width, which follows the look's weight,
1px in Washi and 2px in ICS, and its text is font-sans at the look's UI weight, with the
placeholder in text-fg-subtle. With type="file", the browse button loses its border and
background and reads as 14px medium text inside the field.
Invalid and disabled
Set aria-invalid when the value fails validation. The border turns border-destructive,
the same as on Textarea,
Select, and Checkbox, and
a screen reader announces the field as invalid. Say what is wrong in a
FieldError below it and list the
error's id in aria-describedby, so the message is announced when it appears and read with
the field after that.
<Field>
<FieldLabel htmlFor="email">Email</FieldLabel>
<Input
id="email"
type="email"
aria-invalid={Boolean(error)}
aria-describedby={error ? 'email-error' : undefined}
/>
<FieldError id="email-error">{error}</FieldError>
</Field>disabled drops the field to 64% opacity with a not-allowed cursor, and a Field around it
dims its label to match. readOnly has no style of its own, so a read-only Input looks the
same as one that can be edited.
Enter an email address, like name@example.com.
Height and text size
Input is 40px tall, the height of a md Button and a
Select trigger, and unlike Button it does not grow on a touch screen. Set another height
with a class like h-9. Its text is 16px at every width, because iOS Safari zooms the page
in when a field with smaller text takes focus, so on an iPhone the page stays put.
Accessibility
- It renders a native
<input>, so typing, selection, autofill, and form submission work as the browser provides them. - It has no name of its own. Name it with a FieldLabel whose
htmlFormatches itsid, or witharia-labelwhen there is no visible label. A placeholder is not a label, since it disappears as soon as someone types. The placeholder is intext-fg-subtle, a hint the label does not depend on, so it does not read as a typed value. When it shows an example, start it with "e.g." or put the example in a FieldDescription. - Focus shows a 2px ring in the contrast ink, flush against the border, on
:focus-visible. A text field matches:focus-visibleon a click as well as from the keyboard, so the ring shows whenever the field has focus. - In forced colors the ring is dropped and a transparent 2px outline takes its place, which the system paints, so focus stays visible in Windows high contrast.
aria-invalidpaints the borderborder-destructiveand makes a screen reader announce the field as invalid. Forced colors repaints the border in a system color, so the FieldError message is the sign that holds up there.disabledsets the native attribute, so the field leaves the tab order and assistive tech reports it as unavailable.- It is 40px tall and as wide as its container, and does not grow on a touch screen.
- Nothing animates. The border and the ring change at once.
When to use something else
- Textarea for text that runs past one line, like a comment or a description.
- Input group for an icon or a short suffix inside the field, like a search glass or a domain.
- Select to pick one of a few known values, and Combobox when the list is long enough to search.
- Date picker for a date, picked from a calendar rather than typed.
Install
shadcn add @gesso/input