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.

Let's talk Learn more

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#

ClassRoleRendered by
home-hero-button-primaryAccent-filled call to actionlayouts/index.html
home-hero-button-secondaryOutlined companion actionlayouts/index.html
form-submitInk-filled form submitlayouts/_default/contact.html
filter-chip filter-chip-buttonFilter toggle; tag-pill-active when selectedpartials/data-page/filter-row.html
table-sort-button talks-sort-buttonColumn sort control in a table headerReference tables and the talks archive
pagination-buttonPage-number controlpartials/pagination.html
copy-markdown-buttonIcon-only copy actionpartials/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-pressed on filter chips, aria-sort on the <th> column header that contains a sort button, and aria-current="page" on the active page number
  • The icon-only copy-markdown-button carries an aria-label, a matching title, and an sr-only text span; both icon images are aria-hidden with empty alt
  • Focus stays where the user put it — the scripts listen for click only 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 the button role