surface · command

Button

Available now

Ship a command surface that looks like your brand and behaves the same on web and Flutter. You author the Button once as a YAML contract; The Wyrding Way projects it into React, Flutter, and Lit with parity gated in CI.

  • PlatformsReact · Flutter · Lit
  • States5
  • Contractbutton.yaml
01

Live example

The same contract, re-skinned per brand.

In the shipped docs this brand switcher is live. Here it is mocked: static side-by-side renders under each preset, with the chips shown for shape only.

brand: TWW Material Carbon HIG
01TWW · Gilt & Ink
02Inspired by Material
03Inspired by Carbon
04Inspired by Apple HIG
02

Contract

The single source of truth.

Change this and every platform regenerates. The drift gate fails the build until React, Flutter, and Lit agree.

button.contract.yaml source
01component: Button02surface: command03slots:04  - name: label05    required: true06events:07  - name: press08states:09  - default10  - hover11  - pressed12  - disabled13  - loading14tokens:15  - color.primary16  - color.on-primary17  - radius.control18  - focus.ring19a11y:20  role: button21  keyboard: [Enter, Space]
03

Props

The authored surface.

PropTypeDefaultDescription
variant "primary" | "secondary" | "ghost" "primary" Visual weight. Primary carries the main action; ghost stays quiet until hover/focus.
size "sm" | "md" | "lg" "md" Padding and type scale from your brand density tokens.
disabled boolean false Blocks activation and announces the disabled state to assistive tech.
loading boolean false Shows a progress affordance and keeps the control non-interactive until the action settles.
type "button" | "submit" | "reset" "button" Native button type for forms.
onPress () => void Fires when the user activates the control via pointer or keyboard.
04

Accessibility

Obligations, checked in CI.

These are contract obligations, verified by the pipeline — not review-time suggestions.

  1. 01Keyboard: Enter and Space activate; focus order follows DOM order.
  2. 02Focus visible: uses your brand focus-ring tokens — never remove the ring without a replacement that meets 3:1.
  3. 03Name: the accessible name comes from children text, or aria-label when the label is icon-only.
  4. 04Disabled: uses aria-disabled when you need the control to remain focusable for explanation; otherwise the native disabled attribute.
  5. 05Contrast: primary fills must meet WCAG AA against their on-primary text — the token pipeline fails the build if they do not.
05

Token references

Every value resolves through tokens.

Nothing is hard-coded; the coverage check flags anything that is.

TokenRole
color.primary Fill for primary variant
color.on-primary Label on primary fill
color.primary-hover Hover fill
color.primary-pressed Pressed fill
radius.control Corner radius
space.control-x / space.control-y Horizontal and vertical padding
type.label Label typography
motion.duration.short / motion.easing.standard Hover and press transitions
focus.ring Keyboard focus indicator