SYSTEM

Field

A label, a control whose only line is its ink rule, and help or an error under it.

Forms shadcn: Input, Label, Form

Only used to reply.

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.