ComponentsLumos 0.0.1UpdatedOpen component

Button

A button or a link — written or a mark on its own — that knows which element it should be.

One component, two elements. A Button that goes somewhere renders an <a>; a Button that does something renders a <button>. That distinction matters more than it looks: it decides whether the keyboard activates it with Enter or Space, whether it can be opened in a new tab, and how a screen reader announces it.

Two props describe the rest of it, and they answer different questions. variant is what kind of button it is — written, or a mark on its own. emphasis is how much weight it carries on the page it sits on.

astro
<Button>Primary</Button>
<Button emphasis="secondary">Secondary</Button>
<Button variant="link" element="link" href="/docs">Link</Button>

Kinds

main and link are written: whatever you put inside them is the label. play, close and arrow are a mark on their own, and 0.0.2 folded them in from the separate components they used to be. Each carries its own accessible name — Play, Pause, Close, Next, Previous — so a mark-only button is never announced as an unnamed button. Set label when yours does something more specific.

astro
<Button variant="play" />
<Button variant="play" pressed />
<Button variant="close" />
<Button variant="arrow" direction="back" />
<Button variant="arrow" />

The mark-only kinds, each with the label it announces itself by.

Props

PropTypeDefaultWhat it does
renderbooleantrueSet to false to skip this component and everything inside it.
variant"main" | "link" | "play" | "close" | "arrow""main"What kind of button it is. main and link are written; the rest are a mark on their own.
emphasis"primary" | "secondary""primary"How much weight it carries. primary is filled, secondary is outlined, for anything sitting beside a primary. Not available on link, which is already the quietest.
element"button" | "link""button"Which element it renders as. link renders an <a> and takes href; button renders a <button> and takes type and disabled.
hrefstringNoneWhere the link goes. Links only.
type"button" | "submit" | "reset""button"What the button does inside a form. Buttons only.
disabledbooleanNoneGreys it out and stops it responding. Buttons only.
labelstringNoneWhat the control does, for anyone who cannot see its mark. Only on play, close and arrow, which each supply their own if you do not.
pressedbooleanfalseWhether it is playing: shows the pause mark and reads as pressed. play only.
direction"forward" | "back""forward"Which way the arrow points, and whether it announces itself as Next or Previous. arrow only.

Colors come from the theme

A button never sets its own colors. It reads --button-background, --button-text and their hover pairs from the nearest theme, so the same <Button> is correct on a light section, a dark one and a brand-colored one without a single extra class.

astro
<Section theme="brand">
  <Button>Readable here too</Button>
</Section>

Writing the label

The text inside the button is what a screen reader announces and what a voice-control user says out loud. "Read the pricing" works; three buttons on one page all saying "Read more" do not.