Button
Available nowShip 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
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.
Contract
The single source of truth.
Change this 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] Props
The authored surface.
| 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. |
Accessibility
Obligations, checked in CI.
These are contract obligations, verified by the pipeline — not review-time suggestions.
- 01Keyboard: Enter and Space activate; focus order follows DOM order.
- 02Focus visible: uses your brand focus-ring tokens — never remove the ring without a replacement that meets 3:1.
- 03Name: the accessible name comes from children text, or aria-label when the label is icon-only.
- 04Disabled: uses aria-disabled when you need the control to remain focusable for explanation; otherwise the native disabled attribute.
- 05Contrast: primary fills must meet WCAG AA against their on-primary text — the token pipeline fails the build if they do not.
Token references
Every value resolves through 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 |