action — wyrd.component.button
Button
Action primitive that emits one canonical press event from pointer, keyboard, and assistive activation.
Install @wyrd-company/react, @wyrd-company/lit, or the Flutter
package and use it directly — your DESIGN.md does the styling.
catalog/contracts/button.yml source of truth · verbatim $schema: https://thewyrdingway.dev/schemas/component-contract.schema.ymlcontractVersion: 0.1.0identity: name: Button tag: wyrd-button package: wyrd.component.button title: Button summary: Action primitive that emits one canonical press event from pointer, keyboard, and assistive activation.relationships: related-to: - lit-target-projection-pilot - quality-parity-and-gatesclassification: category: action composition: multi-slot interactive: truetarget-strategy: react: required flutter: required lit: requiredsurface: properties: - name: variant type: kind: enum values: - primary - secondary - ghost - danger required: false default: primary reflects: true serializable: true summary: Visual and semantic action emphasis. - name: is-disabled type: kind: boolean required: false default: false reflects: true serializable: true summary: Prevents activation and exposes disabled platform semantics. - name: is-loading type: kind: boolean required: false default: false reflects: true serializable: true summary: Shows pending action state while preserving dimensions and suppressing duplicate activation. slots: - name: label content: true required: true cardinality: exactly-one accepts: - text - node summary: Primary visible label and accessible-name source. - name: leading-icon required: false cardinality: zero-or-one accepts: - icon summary: Optional icon before the label in inline flow. - name: trailing-icon required: false cardinality: zero-or-one accepts: - icon summary: Optional icon after the label in inline flow. events: - name: press payload: source: kind: enum values: - pointer - keyboard - assistive action: kind: action-ref bubbles: true composed: true cancelable: true summary: Canonical activation event emitted once per accepted activation. states: - name: default source: platform summary: Idle enabled state. - name: hover source: interaction summary: Pointer hover state on hover-capable devices. - name: focus-visible source: platform summary: Keyboard-visible focus state. - name: pressed source: interaction summary: Active press state. - name: disabled source: property summary: Disabled state derived from is-disabled. - name: loading source: property summary: Pending state derived from is-loading. parts: - name: root summary: Interactive platform control root. slots: - label - leading-icon - trailing-icon - name: label summary: Label content container. slots: - label - name: icon summary: Icon slot containers. slots: - leading-icon - trailing-icon tokens: primary: background: color.primary background-hover: color.primary-hover background-pressed: color.primary-pressed foreground: color.on-primary secondary: background: color.secondary foreground: color.on-secondary ghost: background: transparent foreground: color.primary danger: background: color.error foreground: color.on-error disabled: background: color.disabled foreground: color.on-disabled radius: rounded.md padding-x: spacing.lg padding-y: spacing.sm gap: spacing.sm label: typography.label-mdmessages: []obligations: accessibility: role: button name: Label slot or aria-label provides the accessible name. keyboard: - Enter activates the button. - Space activates the button. semantics: - Disabled state is exposed through native disabled semantics where the target has them. - Loading state keeps the accessible name stable and prevents duplicate activation. behavior: model: stateless interactions: - Activation emits press when the button is enabled and not loading. - Touch activation does not create hover state. hostEffects: - Dispatch activation event. - Invoke action binding for SDUI when present. conditions: - rtl - reduced-motion - cvd-deuteranopia - density-compact sdui: status: serializable serializableProperties: - variant - is-disabled - is-loading serializableSlots: - label - leading-icon - trailing-icon eventBindings: - press notes: Press serializes as an action reference; executable callbacks stay target-local.examples: - name: primary state: default properties: variant: primary slots: label: Save changes - name: loading state: loading properties: variant: primary is-loading: true slots: label: Save changes - name: danger state: default properties: variant: danger slots: label: Delete
01
Examples
Generated from the contract's examples block. Previews render from the
Playground tokens — change a value there and everything below follows.
primary state: default
import { Button } from "@wyrd-company/react";
<Button variant="primary" onPress={onPress}>
Save changes
</Button>
import 'package:wyrd/wyrd.dart';
WyrdButton(
variant: WyrdVariant.primary,
onPress: onPress,
child: Text('Save changes'),
)
import "@wyrd-company/lit/button.js";
<wyrd-button variant="primary" @press=${onPress}>
Save changes
</wyrd-button>
loading state: loading
import { Button } from "@wyrd-company/react";
<Button variant="primary" isLoading onPress={onPress}>
Save changes
</Button>
import 'package:wyrd/wyrd.dart';
WyrdButton(
variant: WyrdVariant.primary,
isLoading: true,
onPress: onPress,
child: Text('Save changes'),
)
import "@wyrd-company/lit/button.js";
<wyrd-button variant="primary" is-loading @press=${onPress}>
Save changes
</wyrd-button>
danger state: default
import { Button } from "@wyrd-company/react";
<Button variant="danger" onPress={onPress}>
Delete
</Button>
import 'package:wyrd/wyrd.dart';
WyrdButton(
variant: WyrdVariant.danger,
onPress: onPress,
child: Text('Delete'),
)
import "@wyrd-company/lit/button.js";
<wyrd-button variant="danger" @press=${onPress}>
Delete
</wyrd-button>
02
Anatomy
Callouts read from the contract: the parts map, token bindings, and the
required label slot.
ANATOMYButtoncontract-fed FIG. 1 parts: root · label · icon TOL. ±0
03
Properties
| Name | Type | Default | Summary |
variant | primary | secondary | ghost | danger | primary | Visual and semantic action emphasis. |
is-disabled | boolean | false | Prevents activation and exposes disabled platform semantics. |
is-loading | boolean | false | Shows pending action state while preserving dimensions and suppressing duplicate activation. |
04
Slots & events
| Slot | Cardinality | Accepts | Summary |
label | exactly-one | text, node | Primary visible label and accessible-name source. |
leading-icon | zero-or-one | icon | Optional icon before the label in inline flow. |
trailing-icon | zero-or-one | icon | Optional icon after the label in inline flow. |
| Event | Payload | Summary |
press | source, action | Canonical activation event emitted once per accepted activation. |
05
Tokens
The contract's token bindings. Color swatches show the value of the brand currently
selected in the Playground.
| Binding | Token | |
primary.background | color.primary | |
primary.background-hover | color.primary-hover | |
primary.background-pressed | color.primary-pressed | |
primary.foreground | color.on-primary | |
secondary.background | color.secondary | |
secondary.foreground | color.on-secondary | |
ghost.background | transparent | |
ghost.foreground | color.primary | |
danger.background | color.error | |
danger.foreground | color.on-error | |
disabled.background | color.disabled | |
disabled.foreground | color.on-disabled | |
radius | rounded.md | |
padding-x | spacing.lg | |
padding-y | spacing.sm | |
gap | spacing.sm | |
label | typography.label-md | |
06
States
| State | Source | Summary |
default | platform | Idle enabled state. |
hover | interaction | Pointer hover state on hover-capable devices. |
focus-visible | platform | Keyboard-visible focus state. |
pressed | interaction | Active press state. |
disabled | property | Disabled state derived from is-disabled. |
loading | property | Pending state derived from is-loading. |
07
Accessibility
From the contract's accessibility obligations. Role button;
Label slot or aria-label provides the accessible name.
- Enter activates the button.
- Space activates the button.
- Disabled state is exposed through native disabled semantics where the target has them.
- Loading state keeps the accessible name stable and prevents duplicate activation.
- Verified under: rtl, reduced-motion, cvd-deuteranopia, density-compact.
08
SDUI
Status: serializable. Press serializes as an action reference; executable callbacks stay target-local.
| Serializable | Members |
| Properties | variant, is-disabled, is-loading |
| Slots | label, leading-icon, trailing-icon |
| Events | press |