Button
Available nowsurface: command
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.
01 Live example
The brand switcher is live in the shipped docs. Here it is mocked as static specimens — the same Button under each preset.
Brand
02 The contract
This YAML is the single source. Change it and every platform regenerates; the drift gate holds the build until React, Flutter, and Lit agree.
component: Button
surface: command
slots:
- name: label
required: true
events:
- name: press
states:
- default
- hover
- pressed
- disabled
- loading
tokens:
- color.primary
- color.on-primary
- radius.control
- focus.ring
a11y:
role: button
keyboard: [Enter, Space]
03 Props
| Prop | Type | Default | Description |
|---|---|---|---|
| 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 declared in the contract and checked in CI — not review-time suggestions.
- Keyboard: Enter and Space activate; focus order follows DOM order.
- Focus visible: uses your brand focus-ring tokens — never remove the ring without a replacement that meets 3:1.
- Name: the accessible name comes from children text, or aria-label when the label is icon-only.
- Disabled: uses aria-disabled when you need the control to remain focusable for explanation; otherwise the native disabled attribute.
- Contrast: 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 visual value resolves through your brand's tokens. Hard-code nothing; the coverage check flags what is unresolved.
| Token | Role |
|---|---|
| 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 |