---
title: Button
description: Buttons trigger actions in the interface. Choose a variant that reflects importance.
category: Actions
---
import { meta as ButtonMeta, Default, Destructive, Ghost, Link } from '@/content/stories/button';
import Canvas from '@/components/component-docs/canvas';
import Demo from '@/components/component-docs/demo';
export const config = {
dependencies: {
components: [Canvas, Demo],
scripts: [
'../../components/component-docs/demo.script.tsx',
'../../components/component-docs/canvas.script.tsx',
'../../components/component-docs/controls.script.tsx',
],
},
};
# Button
Buttons trigger actions in the interface. Choose a variant that reflects importance, and write labels that describe the outcome, not the control type.
## Try it
## Usage
Import `RuiButton` from the focused module. The default `filled` variant suits the primary action in a small context.
```tsx
import { RuiButton } from '@ecopages/radiant-ui/button';
Save changes
```
## Choose a tone
Use `filled` for the main action, `outline` for a supporting action, and `ghost` when the action should recede until needed. `link` looks like inline navigation copy and underlines on hover and focus; pair it with `size="none"` in running text. `destructive` is for irreversible operations.
Pass `href` when the control should navigate; `variant` only changes appearance.
Use the `square` modifier for an icon-only action. It keeps the selected control size on both axes; provide an `aria-label` because it has no visible text.
```tsx
```
## Theming
Button variants map to **semantic action roles** from the active theme, not Tailwind palette steps (`blue-500`, `red-500`, …):
| `variant` | Semantic role | Typical utilities on `.rui-button--*` |
| --- | --- | --- |
| `filled` | `primary` | `bg-primary`, `text-on-primary` |
| `outline` | surface + `border` | `bg-transparent`, `text-on-background`, `border-border` |
| `ghost` | surface-container | `bg-transparent`, `text-on-surface`, hover `bg-surface-container-low` |
| `destructive` | `error` (destructive) | `bg-error`, `text-on-error` |
| `link` | `link` | `text-link`, underline on hover/focus |
Pressed (toggle) states keep the same role family with a stronger fill (`bg-primary-dark`, `bg-error-dark`) and a focus ring. Brand color packs remap all roles for light and dark mode.
Override at the theme layer (`tokens/presets/colors/*.css`), not in component CSS. `destructive` reuses the `error` status family, matching alerts and toasts.
## Accessibility
- Write labels that describe the resulting action, such as "Save changes".
- Keep disabled buttons explainable with nearby supporting text when needed.
- Do not use color as the only way to communicate action priority or status.
- Set `aria-label` when a button has no visible text (icon-only buttons).
- Toggle buttons set `aria-pressed` when `toggle` / `pressed` are used.
## API
`RuiButton` is a presentational JSX view over a native `