Documents v0.9.0 · previews run the real runtime · experimental features are marked exp

Signup form

A text field, a select and a checkbox feed a live preview, and Reset clears both.

Live previewreal runtime

Type a name, pick a plan, tick the checkbox, then press Reset.

How it works

  • state()line 3Makes each matching element the owner of an independent state with an initial value.
  • :on()lines 6, 7, 8, 11An event rule: when the event happens on the matched element (or inside it, for bubbling events), the rule’s state mutations run. The cascade picks one winning mutation per state, per trigger and per element.
  • event()lines 6, 7, 8Inside a mutation of an :on() rule: one field of the current event, such as event(local-x), event(key) or event(value), read once as a typed value.
  • contentlines 13, 14On elements, a content value that reads state also becomes the element’s DOM text: a real text node, never HTML. The native declaration is kept as written.
  • :when()lines 13, 15Matches elements for which the condition is true, with states resolved from that element.

Native form controls feeding a preview that is outside them. Each control copies its value into a state on the section with an :on(input) or :on(change) rule; the preview reads the states as DOM text.

Native CSS alternative

None for the preview: CSS can match :checked, :placeholder-shown or :invalid, but it cannot read a field’s text or a select’s value into another element.

Limitations

  • The copies are one-way: a change of --name from another rule does not change the field. For a field that must follow its state, use state("", bind(value)) on the field itself (see the Form mirror example).
  • If the browser restores the form after a reload, the preview shows the defaults until the next change.

Implementation

2 files · 15 lines
style.cssreactive
/* ---- Reactive CSS -------------------------------------------------------------------------- *//* The preview is outside the controls, so the states live on the section around both. */.signup { --name: state(""); --plan: state("basic"); --news: state(false); }/* Each control copies its value up when it changes. */.signup input[type="text"]:on(input) { --name: set(event(value)); }.signup select:on(change) { --plan: set(event(value)); }.signup input[type="checkbox"]:on(change) { --news: set(event(checked)); }/* Reset restores the controls natively; the states follow. */.signup:on(reset) { --name: set(""); --plan: set("basic"); --news: set(false); }.signup:when(--name != "") .name { content: var(--name); }.signup .plan { content: var(--plan); }.signup:when(--news) .badge { display: inline; }
state()Function · hover any red tokenMakes each matching element the owner of an independent state with an initial value.Reference →

Source: site/src/catalog/interfaces/signup-form/. style.css from its Reactive CSS divider; the layout above it and the shared api.css run but are not shown.

Related

Task list

Native checkboxes whose label fades when done, with a short animation when a task is checked or unchecked.

state()event():just-checkedwhen()

Pricing toggle

A billing switch changes the price and shows the annual saving, with role="switch" kept in sync.

experimentalstate()toggle()--attr-*when()content

Tabs

Tabs selected by click or arrow keys, with the ARIA tab pattern written from one state.

experimentalstate():on()cycle():nth-var()--attr-*focus: