fjord-uiv0.1.0 / generation 1, "sounding"

fj-btn

The control. Every state in spec 1.11 that applies to a button, in both schemes. A control is one row tall (--fj-row), because DENS-1 makes the single-line row the system's unit and a control that is taller than a row of data would be the loudest thing on a dense page.

Light

rest

Three variants. Outline is the default.

hover

Pointer only. The surface lifts and the label steps up one rung; nothing moves, because a hover that changes a dimension moves everything after it (STATE-HOVER).

focus-visible

--fj-ring-width solid --fj-ring at --fj-ring-offset, square corners regardless of the control's own radius. :focus-visible only, so a mouse click does not ring. `outline: none` appears nowhere in the system (STATE-FOCUS-1..3, AP-8).

active

The background deepens one surface step. No transform, no scale (AP-9).

disabled

Text to --fj-faint, border to --fj-rule, cursor not-allowed, no hover response. --fj-faint clears 4.5:1 on every surface it is permitted to sit on: disabled is not an excuse to stop being legible (STATE-DISABLED).

loading

aria-busy, the label reads a word, and the control is inert so an in-flight action cannot be started twice. No spinner, no shimmer, no pulse: a shimmer is ambient motion wearing a loading costume (MOT-3, AP-9).

long content

A control does not wrap. It grows, and the layout around it decides.

as a link

button_class() gives an <a> the same look, which is the only element other than <button> that ever carries it. The ring comes from the component's own rule rather than from the base layer, so a linked control rings identically.

attrs passthrough

Anything the caller passes reaches the element, and a class among it is APPENDED to the component's rather than replacing it. The appended utility wins, because the component layer is @layer components and a utility is @layer utilities.

unstyled

The escape hatch: the element, the structure and the aria wiring, without the fj-* classes. For the case where the system is wrong about the look and right about the behaviour. Two call sites reaching for it means the component is wrong.

Dark

rest

Three variants. Outline is the default.

hover

Pointer only. The surface lifts and the label steps up one rung; nothing moves, because a hover that changes a dimension moves everything after it (STATE-HOVER).

focus-visible

--fj-ring-width solid --fj-ring at --fj-ring-offset, square corners regardless of the control's own radius. :focus-visible only, so a mouse click does not ring. `outline: none` appears nowhere in the system (STATE-FOCUS-1..3, AP-8).

active

The background deepens one surface step. No transform, no scale (AP-9).

disabled

Text to --fj-faint, border to --fj-rule, cursor not-allowed, no hover response. --fj-faint clears 4.5:1 on every surface it is permitted to sit on: disabled is not an excuse to stop being legible (STATE-DISABLED).

loading

aria-busy, the label reads a word, and the control is inert so an in-flight action cannot be started twice. No spinner, no shimmer, no pulse: a shimmer is ambient motion wearing a loading costume (MOT-3, AP-9).

long content

A control does not wrap. It grows, and the layout around it decides.

as a link

button_class() gives an <a> the same look, which is the only element other than <button> that ever carries it. The ring comes from the component's own rule rather than from the base layer, so a linked control rings identically.

attrs passthrough

Anything the caller passes reaches the element, and a class among it is APPENDED to the component's rather than replacing it. The appended utility wins, because the component layer is @layer components and a utility is @layer utilities.

unstyled

The escape hatch: the element, the structure and the aria wiring, without the fj-* classes. For the case where the system is wrong about the look and right about the behaviour. Two call sites reaching for it means the component is wrong.