Button
Buttons are for explicit commands. Use clear labels or familiar icons, keep hit areas stable, and reserve stronger styles for actions that need priority. There is no shared .button class to put in markup: each context still defines its own class in assets/css/site.css, and all of them share one shape — an uppercase or bold label, a squared border, and an accent hover. Four of those classes — home-hero-button, form-submit, table-sort-button/talks-sort-button, and pagination-button — compose a shared .btn-base primitive (inline-flex items-center font-[700] transition-colors) internally in the stylesheet, so the layout and interaction behaviour they genuinely have in common is written once. Border, fill, padding, and uppercase stay per-class because those differ by design. filter-chip/anchor-index-link (baseline-aligned pill shape) and copy-markdown-button (icon-only, opacity-based) are a different visual family and intentionally do not use .btn-base.
When to use#
- Use a button for an explicit command — submit, sort, filter, copy — something that acts on the current page
- Style a link as a button only when it is the page’s call to action; ordinary navigation stays a text link
- Use clear labels or familiar icons; the label names the command, not the mechanism
- Keep hit areas stable — a state change such as an active filter or a sort direction may restyle the button, but it must not resize it
- Reserve the filled styles (accent or ink) for the one action that needs priority; companion actions take the outlined style
Implementation#
<div class="home-hero-actions">
<a class="home-hero-button home-hero-button-primary" href="/en/contact/">Let's talk</a>
<a class="home-hero-button home-hero-button-secondary" href="/en/about/">Learn more</a>
</div>
<button type="submit" class="form-submit">Send message</button>All button styling is component classes in assets/css/site.css; there is no button partial and no JavaScript of its own. A <button> element carries type="button" unless it submits a form, and stateful controls expose their state through attributes the CSS styles directly: aria-pressed on filter chips, aria-sort on table column headers, aria-current on the active page number.
Variants#
| Class | Role | Rendered by |
|---|---|---|
home-hero-button-primary | Accent-filled call to action | layouts/index.html |
home-hero-button-secondary | Outlined companion action | layouts/index.html |
form-submit | Ink-filled form submit | layouts/_default/contact.html |
filter-chip filter-chip-button | Filter toggle; tag-pill-active when selected | partials/data-page/filter-row.html |
table-sort-button talks-sort-button | Column sort control in a table header | Reference tables and the talks archive |
pagination-button | Page-number control | partials/pagination.html |
copy-markdown-button | Icon-only copy action | partials/copy-as-markdown.html |
The two home-hero-button-* variants extend the home-hero-button base. home-hero-button, form-submit, table-sort-button/talks-sort-button, and pagination-button all compose the shared .btn-base primitive internally; filter-chip filter-chip-button and copy-markdown-button stand alone as separate visual families.
Interface manifest
- Kind
- Component
- Category
- Action
- Status
- Implemented
- Implementation
- CSS:
assets/css/site.css
Accessibility#
- Every command is a native
<button>— submit, filter, sort, copy — so Enter and Space activate it with no scripted key handling; the two hero calls to action are<a>elements and activate with Enter - State rides on standard attributes the scripts keep in sync:
aria-pressedon filter chips,aria-sorton the<th>column header that contains a sort button, andaria-current="page"on the active page number - The icon-only
copy-markdown-buttoncarries anaria-label, a matchingtitle, and ansr-onlytext span; both icon images arearia-hiddenwith emptyalt - Focus stays where the user put it — the scripts listen for
clickonly and never move focus - Avoid building a command from a
<div>or<span>with a click handler; only the native element gives keyboard activation and thebuttonrole