Actions
Button
Uppercase, letter-spaced labels on a 2px border, as on jsonresume.org. Buttons do things; links go places.
import { Button } from '@jsonresume/ui'Source(opens in a new tab)
Playground
Change the props and copy the result.
jsx
<Button variant="primary" size="md">Export PDF</Button>Examples
button/variants.tsx
import { Button } from '@jsonresume/ui';
export default function ButtonVariants() {
return (
<>
<Button variant="primary">Get started</Button>
<Button>View themes</Button>
<Button variant="ink">Sign in</Button>
<Button variant="ghost">Cancel</Button>
<Button variant="danger">Delete</Button>
<Button variant="link">Learn more</Button>
</>
);
}button/sizes.tsx
import { Button } from '@jsonresume/ui';
export default function ButtonSizes() {
return (
<>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg" variant="primary">
Read more
</Button>
</>
);
}button/states.tsx
import { Button } from '@jsonresume/ui';
export default function ButtonStates() {
return (
<>
<Button variant="primary" loading>
Publishing
</Button>
<Button disabled>Disabled</Button>
<Button size="icon" aria-label="Search">
<svg
viewBox="0 0 16 16"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
aria-hidden="true"
>
<circle cx="7" cy="7" r="4.5" />
<path d="m10.5 10.5 3 3" strokeLinecap="round" />
</svg>
</Button>
</>
);
}button/as-link.tsx
import { Button } from '@jsonresume/ui';
// asChild renders the child element (here a link, or a Next.js <Link>)
// with button styles, so navigation stays a real link.
export default function ButtonAsLink() {
return (
<Button asChild variant="primary">
<a href="https://jsonresume.org/getting-started">Getting started</a>
</Button>
);
}Usage
Do
- Use one primary button per view, for the action most people came to take.
- Write labels as short verbs: "Publish", "View themes".
- Use asChild with a link for navigation.
Don’t
- Put two primary buttons side by side.
- Use the danger variant for anything that is not destructive.
- Disable a button without explaining what is missing nearby.
Accessibility
- Renders a native <button type="button"> by default, so forms are not submitted by accident.
- Icon-only buttons need an aria-label.
- loading sets aria-busy and disabled while keeping the accessible name.
- Focus shows a 2px ring in the focus token, never removed.
Props
<Button>
| Prop | Type | Default | Description |
|---|---|---|---|
| asChild | boolean | false | Render the single child (e.g. a link) with button styles instead of a
<button>. loading is not available in this mode. |
| fullWidth | boolean | – | Style variant. |
| loading | boolean | false | Shows a spinner, keeps the button's width, and disables it. |
| size | iconsmmdlg | md | Style variant. |
| variant | linkprimaryinkdangersecondaryghost | secondary | Style variant. |