Button
The primary action control — primary, accent, secondary, and ghost variants in three sizes.
import { Button } from '@elirobinson/react/components/atoms/Button';Styles: @elirobinson/react/styles/atoms/Button.css — already included when you import @elirobinson/react/styles.css.
Show code
import { Button } from '@elirobinson/react/components/atoms/Button';
export default function Basic() {
return <Button onClick={() => alert('Shipped.')}>Get started</Button>;
}When to use it
Use Button for actions — submitting a form, opening a dialog, confirming a step. For
navigation, use a real link: an <a> styled as a link is honest about what happens on
click, works with middle-click and cmd-click, and needs no JavaScript.
- primary is the default: ink-solid, one per view is a good ceiling.
- accent is Miltinson Amber — reserve it for the one action I most want taken.
- secondary is the bordered workhorse for everything alongside a primary.
- ghost sits in toolbars and card corners where a border would add noise.
Variants
Show code
import { Button } from '@elirobinson/react/components/atoms/Button';
export default function Variants() {
return (
<div className="demo-row">
<Button variant="primary">Primary</Button>
<Button variant="accent">Accent</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
</div>
);
}Sizes
All three sizes keep the 44×44px minimum touch target — the smaller sizes shrink the visible control, not the hit area.
Show code
import { Button } from '@elirobinson/react/components/atoms/Button';
export default function Sizes() {
return (
<div className="demo-row">
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
);
}Disabled
Show code
import { Button } from '@elirobinson/react/components/atoms/Button';
export default function States() {
return (
<div className="demo-row">
<Button disabled>Disabled</Button>
<Button variant="secondary" disabled>
Disabled secondary
</Button>
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | md | — |
variant | "primary" | "accent" | "secondary" | "ghost" | primary | — |
Also accepts all ButtonHTMLAttributes<HTMLButtonElement> props.
Accessibility
- Renders a native
<button>withtype="button"by default, so a button inside a form never submits it by accident — passtype="submit"when submitting is the point. - Keyboard:
Tabfocuses,EnterandSpaceactivate. That contract comes from the native element; nothing re-implements it. - Focus is marked with the system's high-contrast ink ring (
:focus-visible), never removed. - The ref forwards to the underlying
<button>element, so focus management from a parent (ref.current.focus()) works directly. - Icon-only buttons need an
aria-label— the component doesn't invent one.
Do
- Use one primary or accent button per view — hierarchy is the point.
- Write button labels as verbs: "Save changes", not "Changes".
- Pass type="submit" explicitly inside forms when submitting is intended.
- Give icon-only buttons an aria-label.
Don't
- Use a Button for navigation — style a link instead.
- Disable a submit button to signal a validation error — show the error and keep it clickable.
- Stack multiple accent buttons in one section; amber is a signal, not a fill.
- Shrink the hit area below 44×44px — density comes from the visible control, not the target.