Button
Every clickable commitment renders through here. It picks the right element for the job and makes loading safe.
Variants
Primary is reserved for the single most important next step per VIEW — not per card, not per section. Two primaries on a screen means neither is.
Solid
The filled neutral-ink CTA, for a view whose accent is already spoken for. The canonical pair is a nav: link on "Sign in", solid on "Open the map". An accent primary in that slot fights whatever else on the page is already accent-coloured.
It paints itself with --gd-surface-solid and --gd-ink-on-solid — the one neutral pair that genuinely flips with the theme, near-black on a light page and near-white on a dark one. Not --gd-surface-inverse, which is deliberately dark in both themes so that a toast, a code block and the footer band stay dark at night. Borrowing inverse here is what shipped a 1.3:1 pill on a charcoal bar — a control with no visible boundary, which is a WCAG 1.4.11 failure and, more plainly, a call to action nobody could see.
Link
A real button that reads as a link, for actions that live in a sentence. An <a href="#"> that performs an action misreports itself to everyone navigating by links; this variant exists so authors stop reaching for that anchor.
A six-digit code is on its way. , or .
Sizes
Icon buttons
States
Block
Which element it renders
The part hand-rolled buttons keep getting wrong.
<GdButton to="/library"> → NuxtLink <GdButton href="https://…"> → <a> <GdButton> → <button type="button"> A div with a click handler is not on the table: it answers Enter, silently ignores Space — which every native button activates on — and is unreachable by keyboard without a tabindex nobody remembers to add. Real navigation also means middle-click and open-in-new-tab work, which a click handler cannot give you.