Field
A label, a control whose only line is its ink rule, and help or an error under it.
States
- Name
Rest
nothing set
The ink rule alone. The label sits half a module above it.
- Name
Focused
:focus
The rule develops in --state, two dots tall, from where you pressed.
- Email
Only used to reply.
With help
aria-describedby
A sentence under the rule, in --muted-foreground.
- Email
Check thisAdd the part after the @.
Invalid
aria-invalid="true"
The rule stays --state and the message leads with “Check this”.
- Name
Disabled
disabled
The rule drops to a --border hairline and the text to --muted-foreground.
Anatomy
| Height | 40px (--control) |
|---|---|
| Line | one 1px --ink rule under the control; no box |
| Text | Basier Square 16/24; placeholder in --muted-foreground |
| Label | the label voice, 11/16, half a module above the control |
| Help, error | 16/24, half a module under the rule |
| Focus | a 4px --state rule develops from the press in 140ms, from the middle by keyboard |
| Fire | 280ms flare where the rule starts |
| Invalid | aria-invalid="true": the rule stays --state and a “Check this” label leads the message |
| Spacing | fields a module apart; the submit is the page’s solid button |
The dot and timings are read from the engine at build time (rule.ts), not typed in here.
Decisions
-
The rule is the focus
A field has no box to colour, so focus is its rule developing in --state from where you pressed. It is the focus indicator, so no outline is drawn as well.
-
Invalid is a state
An error is the one place --state shows without a hover: an invalid field is a state. A warning or a destructive action is not, and is told by its glyph and words, in ink.
-
Frames off
A field’s only line is its ink rule. A border round the input would make it an object on the page, as cards were before the frames came off.
-
On the module
The artifact drew label, control and message 8px apart. Here they are half a module apart, so the field stands on the same 24px module as the page.