Button
The action and CTA affordance, polymorphic by intent.
The action and CTA affordance. Polymorphic: with href it is an<a> (a CTA that navigates), otherwise a<button> (a real action) — same look, picked by intent rather than by a prop.
primary fills with --surface-action, which is the brand green in both modes (ADR 0014). secondary is an outline that reads --text-default, so it adapts inside tone contexts where a fill would not. A link-styled affordance stays the Link primitive's job — there is deliberately no third variant.
Hover sweeps the fill up from the bottom edge over--duration-base instead of crossfading it in (ADR 0034). The shade is the one the crossfade already used; only the delivery changed.
The layer is revealed with clip-path, not scaled withtransform. Scaling is the usual way to write this and it is wrong here: a squashed box squashes its own border-radius, so mid-sweep the bottom corners flatten and the rising fill reads as a square-ended bar poking out of a rounded button. Hover slowly and watch the corners.
Re-tone the preview and toggle the theme: the green fill is held across both modes and every tone, because --surface-action is not tone-aware on purpose (ADR 0013) — a CTA should read as the brand green wherever it lands.
Variants
Disabled
Only the <button> form has this state: a disabled link is a link you don't render. It drops out of the sweep entirely rather than sweeping in a greyed fill, which would read as a button that responded.
Props
| Prop | Type | Required |
|---|---|---|
| variant | "primary" | "secondary" | — |
| href | string | — |
| type | "button" | "submit" | "reset" | — |
| class | string | — |