Button

Available now

surface: 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:
TWW · Gilt & Ink
Inspired by Material
Inspired by Carbon
Inspired by Apple HIG
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.

button.contract.yaml
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

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

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.

tokenrole
color.primaryFill for primary variant
color.on-primaryLabel on primary fill
color.primary-hoverHover fill
color.primary-pressedPressed fill
radius.controlCorner radius
space.control-x / space.control-yHorizontal and vertical padding
type.labelLabel typography
motion.duration.short / motion.easing.standardHover and press transitions
focus.ringKeyboard focus indicator