Prototype Lab
Two days, twelve seats, one deployed tool.
Pill-shaped action trigger. Primary is terracotta (one per view), secondary is a teal outline, ghost is quiet, danger is destructive.
<div class="mp-cluster">
<button class="mp-button" type="button">Save draft</button>
<button class="mp-button" type="button" data-variant="secondary">See the work</button>
<button class="mp-button" type="button" data-variant="ghost">Cancel</button>
<button class="mp-button" type="button" data-variant="danger">Delete draft</button>
</div>
<div class="mp-cluster">
<button class="mp-button" type="button" data-size="sm">Small</button>
<button class="mp-button" type="button">Default</button>
<button class="mp-button" type="button" data-size="lg">Large</button>
</div>
<div class="mp-cluster">
<a class="mp-button" href="#components" data-variant="secondary">
Read the essay
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</a>
<button class="mp-button" type="button" data-variant="ghost" data-icon-only aria-label="Add to reading list">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
</button>
</div>
Two days, twelve seats, one deployed tool.
Six weeks, online, starting from your classroom.
<div class="mp-grid" data-min="sm" data-gap="4">
<article class="mp-card">
<h3 class="mp-card__title">Prototype Lab</h3>
<p class="mp-card__body">Two days, twelve seats, one deployed tool.</p>
<div class="mp-card__footer"><button class="mp-button" type="button" data-full-width>Join the waitlist</button></div>
</article>
<article class="mp-card">
<h3 class="mp-card__title">AI Literacy I</h3>
<p class="mp-card__body">Six weeks, online, starting from your classroom.</p>
<div class="mp-card__footer"><button class="mp-button" type="button" data-variant="secondary" data-full-width>Read the syllabus</button></div>
</article>
</div>
<div class="mp-cluster">
<button class="mp-button" type="button" disabled>Disabled</button>
<button class="mp-button" type="button" aria-busy="true">Saving</button>
<button class="mp-button" type="button" data-variant="secondary" aria-pressed="true">Following</button>
</div>
Buttons commit an action: submit, save, open, delete. They are pills — rounded, approachable — and every size keeps a 44px touch target on touch screens.
| Variant | Use for | Rule |
|---|---|---|
| (none) | The single most important action in a view | At most one per view — terracotta is the brand's signature accent |
secondary | Alternatives and navigation-like actions | Teal outline; fills teal on hover |
ghost | Low-emphasis actions in toolbars, cards, dialogs | Neutral; shows a wash on hover |
danger | Irreversible destructive actions | Pair with a confirmation step |
<button class="mp-button">.<a class="mp-button" href="…">.aria-pressed, or a Switch.<button type="button"> for actions and <a href> for navigation; never a <div> with a click handler.data-icon-only) must have an aria-label. Icons inside buttons get aria-hidden="true".aria-busy="true" — the label is hidden visually and a spinner appears, but the accessible name stays. Pair with a live region announcing the result.aria-disabled="true" over disabled when the button should stay focusable so users can discover why it is unavailable.secondary.min-height or colors by hand; change a --mp-button-* knob if you must.| Class | Kind |
|---|---|
.mp-button | root |
| Attribute | Values |
|---|---|
data-variant | secondary · ghost · danger |
data-size | sm · lg |
data-icon-only | boolean — presence enables it |
data-full-width | boolean — presence enables it |
States styled: :active :disabled :focus-visible :hover [aria-busy="true"] [aria-disabled="true"] [aria-pressed="true"]. Set the native attribute or ARIA state; there are no state classes.
| Token | Default | Light · dark |
|---|---|---|
--mp-button-bg | var(--color-action-primary) | #B35530 · #D4724F |
--mp-button-bg-hover | var(--color-action-primary-hover) | #9C4E2F · #DA8667 |
--mp-button-fg | var(--color-text-on-accent) | #FFFFFF · #1A1B1F |
--mp-button-fg-hover | var(--mp-button-fg) | #FFFFFF · #1A1B1F |
--mp-button-border | transparent | — |
--mp-button-glow | var(--shadow-glow-warm) | — |
--mp-button-height | var(--size-control-md) | — |
--mp-button-padding | var(--space-6) | — |
--mp-button-font-size | var(--text-body) | — |
Design tokens consumed: --border-width-medium --color-action-primary --color-action-primary-hover --color-action-secondary --color-bg-hover --color-bg-primary --color-error --color-error-hover --color-text-on-accent --color-text-primary --duration-loop --ease-in-out --focus-ring --focus-ring-offset --font-sans --leading-label --radius-full --shadow-glow-teal --shadow-glow-warm --size-control-lg --size-control-md --size-control-sm --space-2 --space-4 --space-6 --space-8 --state-disabled-opacity --text-body --text-body-lg --text-small --tracking-small --transition-fast --weight-medium
The build measures each pair for the defaults and for every tone, variant and state that reassigns a token, over page and card surfaces. The ratios below are the worst case in each mode; a pair below its minimum stops the build.
| Use | Pair | Light | Dark | Minimum |
|---|---|---|---|---|
| label | --mp-button-fg on --mp-button-bg | 4.93 | 5.14 | 4.5 |
| label, hover / pressed | --mp-button-fg-hover on --mp-button-bg-hover | 5.51 | 6.19 | 4.5 |