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 same contract, re-skinned. In the docs the brand switcher is live; here it is mocked as static side-by-side renders under each preset.
brand:
02
Contract
This is the single source. Change it and every platform regenerates; the drift gate fails the build until React, Flutter, and Lit agree.
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
| 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
These are obligations in the contract, 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. Nothing is hard-coded; the coverage check flags anything that is.
| 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 |