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 brand switcher is live in the shipped docs. Here it is mocked as static specimens — the same Button under each preset.

Brand
TWW · Gilt & Ink
Inspired by Material
Inspired by Carbon
Inspired by Apple HIG

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

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.
disabledbooleanfalseBlocks activation and announces the disabled state to assistive tech.
loadingbooleanfalseShows a progress affordance and keeps the control non-interactive until the action settles.
type"button" | "submit" | "reset""button"Native button type for forms.
onPress() => voidFires 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.

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