Actions and inputs
Buttons, links, pills, fields, and the theme switch. The things a person presses, reads as a label, or types into.
#Button
A button starts something. Its label says what happens, in the owner’s words: Connect your store, Continue to secure checkout. There is one primary button per view.
Code
<div class="btn-row">
<button type="button" class="btn btn-primary">Continue to secure checkout</button>
<button type="button" class="btn btn-secondary">Manage billing</button>
<button type="button" class="btn btn-danger">Disconnect store</button>
<button type="button" class="btn btn-primary" disabled>Saving…</button>
</div>
#Full width, and a row
Use .btn-block inside a card or form that is one column wide, such as sign-in. Group a primary and its alternatives in .btn-row; add .grow to let the primary take the space.
Code
<div class="btn-row" style="margin-bottom: var(--space-4)">
<button type="button" class="btn btn-primary grow">Continue to secure checkout</button>
<button type="button" class="btn btn-secondary">Cancel</button>
</div>
<button type="button" class="btn btn-primary btn-block">Log in</button>
Do
Connect your store
Say what happens, with a verb and a noun.
Don’t
Submit
Generic labels make the owner read around them to learn what they do.
- Minimum height is 2.5rem (40px). Keep it, even when space is tight.
- Disabled buttons drop to 55% opacity and show a not-allowed cursor. Say why in nearby text when it is not obvious.
- Focus shows a 2px ring in
--color-focus. Never remove it.
#Inline link
.btn-link is for a quiet action that leads somewhere else in the product, usually ending in an arrow: Open store →.
Code
<a class="btn-link" href="#btn-link">Open full report →</a>
Use it when
- Moving to another page, at the end of a card or summary
- A secondary path that should not compete with the primary button
Don’t use it when
- Saving, connecting, paying, or anything that changes data
#Pill
A pill is a short, read-only status. It is never a button. The tone carries the meaning, and the words carry it too, so it never depends on color alone.
Code
<div class="btn-row">
<span class="pill">Monday</span>
<span class="pill pill-accent">● Connected</span>
<span class="pill pill-pop">Latest</span>
<span class="pill pill-warn">Waiting for first report</span>
<span class="pill pill-danger">Failed</span>
</div>
<Pill>Monday</Pill>
<Pill tone="accent">● Connected</Pill>
<Pill tone="pop">Latest</Pill>
<Pill tone="warn">Waiting for first report</Pill>
<Pill tone="danger">Failed</Pill>
| Tone | Means | Examples |
|---|---|---|
| neutral | A fact, not a state | Monday, Sep 21–27, 2026 |
accent | Ready, connected, fine | ● Connected, Ready |
pop | New or current | Latest |
warn | Waiting or needs a look | Waiting for first report |
danger | Failed | Failed |
Violet marks what is newest, such as the latest week. Use it in one or two places per screen. Ready, waiting, and failed are told by accent, warn, and danger.
Use it when
- Showing state: connected, waiting, failed, latest
- Labeling a week range or a schedule in a page header
Don’t use it when
- Anything clickable. Use a button or link
- Long text. Keep it to about three words
- Decoration or counts
#Field
A text field is a label, an input, and optional hint text. Always pair the label with the input using for and id. Placeholder text is not a label.
That email and password don’t match. Check them and try again.
Code
<div class="field">
<label for="f-email">Email</label>
<input id="f-email" type="email" value="[email protected]" />
<div class="field-hint">We send your weekly pack here.</div>
</div>
<div class="field">
<label for="f-ro">Store</label>
<input id="f-ro" type="text" value="Cozy Goods" readonly />
</div>
<p class="form-error" role="alert">That email and password don’t match. Check them and try again.</p>
- Labels sit above the input, 13px, semibold. Hints sit below, 11.5px, muted.
- Read-only fields use the sunken background so they look settled, not broken.
- Show errors in
.form-errorwithrole="alert". Say what went wrong and how to fix it, without apologizing. - Two short fields can share a row with
.row-2. It stacks below 520px.
#Divider
.divider separates two routes through the same form, such as “or” between a password and another way in.
Code
<button type="button" class="btn btn-primary btn-block">Log in</button>
<div class="divider">or</div>
<button type="button" class="btn btn-secondary btn-block">Continue another way</button>
#Theme switch
A three-way segmented control: System, Light, Dark. System removes the data-theme attribute so the OS decides. It lives in Settings under Appearance, and it is the same control in this guide’s top bar.
Code
<div class="segmented" role="group" aria-label="Color theme">
<button type="button" aria-pressed="true">System</button>
<button type="button" aria-pressed="false">Light</button>
<button type="button" aria-pressed="false">Dark</button>
</div>
Use it when
- Choosing one of a few mutually exclusive, instantly applied options
Don’t use it when
- Choosing between pages. Use navigation
- Long lists of options