Button
- How
- An anchor with
.sdc-btn, andvariant=“primary”for the filled version. There is no third weight, no size variants and no disabled state. Filled means slate blue with white text; plain means a transparent fill with a charcoal border. - When
- For the one action you want a visitor to take next. Use the filled version once per screenful, at most. If two buttons sit together, one is filled and the other is not; two filled buttons means the page has not decided what it wants.
- Where
- The hero, and nowhere else on the home page. Inside a case study, links to artifacts render as underlined text instead, not buttons. Navigation between case studies uses the Pager.
One size. Padding is 16px top and bottom and 24px left and right, which is
--sdc-space-sm and --sdc-space-md on the spacing scale, and the corners use
--sdc-radius-sm (10px). That matches the Figma Button. Until October 2026 the
padding was 14px by 22px, which sat off the scale and made the coded button a
little smaller than the Figma one.
In code
Section titled “In code”src/components/ui/Button.astro, with ButtonGroup.astro for a row of them.
---import Button from '../../components/ui/Button.astro';import ButtonGroup from '../../components/ui/ButtonGroup.astro';---<ButtonGroup> <Button href="/labs/plate/" external>Open the Pattern Lab</Button> <Button href="/design-systems">The full practice →</Button></ButtonGroup>| Prop | Type | Default | What it does |
|---|---|---|---|
href |
string | required | Where it goes. Every button on this site is a link. |
variant |
'primary' | 'secondary' |
'secondary' |
Which of the two styles to use. Primary is the filled one, and it is the one action a page wants. |
external |
boolean | false |
Adds target="_blank", rel="noopener" and the hidden “(opens in a new tab)” warning together. |
class |
string | none | Extra classes, for the rare caller that needs to position it. Not the way to set the variant: use variant. |
external is one prop on purpose. The three things it adds have to travel
together, and when they were written by hand they did not always.
Anatomy
Section titled “Anatomy”A button is a single anchor. Its label is its own text, so it also becomes the name a screen reader announces. There is no icon slot. The corner radius is the control radius, 10px, which is deliberately not the card radius of 18px: cards are surfaces, buttons are controls, and the two should not be confused.
States
Section titled “States”Rest and hover only. Hover lifts the button one pixel and darkens the border, or deepens the fill on the primary. Focus is not a button-level style: it comes from the site-wide focus ring, described in Focus.
There is no disabled state because there is nothing on this site a visitor is not allowed to do. If you find yourself needing one, that is a signal the page is doing something it should not.
Accessibility
Section titled “Accessibility”The border on the plain button uses the stronger of the two rule tokens, so the boundary clears the 3 to 1 minimum for a control edge. The weaker rule token measures about 2.5 to 1 and must never be used for a control border. This mistake has been made on this site once already and was caught by a contrast check, not by eye.
Label text must say what happens, not where you are going in the abstract. See Content below.
Content
Section titled “Content”Two to four words. Sentence case. A verb first if the button does something, a noun if it goes somewhere specific.
Avoid a bare verb on its own. “View work” was flagged by an automated audit as ambiguous because the label alone does not say what you would be viewing; it is now “View case studies”. The test is whether the label still makes sense read aloud with no surrounding page.
Do
- Pair one filled button with one plain one.
- Name the destination: “View case studies”, “Resume”.
- Let the label be the accessible name.
Don’t
- Use a button for an artifact link inside a case study.
- Write “Learn more”, “Read more” or “Click here”.
- Add an aria-label that differs from the visible text.
Checks before you ship
Section titled “Checks before you ship”- Read the label out loud with no other page context. Does it say where you land?
- Tab to it. A charcoal ring appears around it, not a browser-blue one.
- Only one filled button is visible at a time.