Button
Buttons with four visual styles, three sizes, a built-in loading state and a focus ring.
Installation
Add component
pnpm dlx @elyri/cli@latest add buttonExamples
Basic
Click to enter the loading state, which resets after 2.5 seconds.
import { useEffect, useState } from 'react';
import { Button } from './components/elyri/Button';
export function Example() {
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!loading) return;
const timer = setTimeout(() => setLoading(false), 2500);
return () => clearTimeout(timer);
}, [loading]);
return (
<Button loading={loading} onClick={() => setLoading(true)}>
Get started
</Button>
);
}Variants
Four visual styles: primary / secondary / ghost / danger.
import { Button } from './components/elyri/Button';
export function Example() {
return (
<div className="demo-ui-row">
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="danger">Delete</Button>
</div>
);
}With icons
An icon before or after the label; iconOnly collapses to a square icon button that needs an aria-label.
import { Button } from './components/elyri/Button';
function PlusIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" aria-hidden="true">
<path d="M12 5v14M5 12h14" />
</svg>
);
}
function ArrowRightIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" aria-hidden="true">
<path d="M5 12h14M13 6l6 6-6 6" />
</svg>
);
}
export function Example() {
return (
<div className="demo-ui-row">
<Button leadingIcon={<PlusIcon />}>New</Button>
<Button variant="secondary" trailingIcon={<ArrowRightIcon />}>
Next
</Button>
<Button variant="secondary" iconOnly aria-label="Add">
<PlusIcon />
</Button>
</div>
);
}Circle
circle squares the button and rounds it fully; handy for icon actions across sizes and variants.
import { Button } from './components/elyri/Button';
function PlusIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2} strokeLinecap="round" aria-hidden="true">
<path d="M12 5v14M5 12h14" />
</svg>
);
}
export function Example() {
return (
<div className="demo-ui-row">
<Button circle aria-label="Add">
<PlusIcon />
</Button>
<Button variant="secondary" circle aria-label="Add">
<PlusIcon />
</Button>
<Button variant="danger" size="sm" circle aria-label="Delete">
<PlusIcon />
</Button>
</div>
);
}Sizes
Three sizes: sm / md / lg.
import { Button } from './components/elyri/Button';
export function Example() {
return (
<div className="demo-ui-row">
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
);
}Loading
Shows a spinner, disables the button and sets aria-busy.
import { Button } from './components/elyri/Button';
export function Example() {
return (
<div className="demo-ui-row">
<Button loading>Submitting</Button>
<Button variant="secondary" loading>
Saving
</Button>
</div>
);
}Disabled
The native disabled state.
import { Button } from './components/elyri/Button';
export function Example() {
return (
<div className="demo-ui-row">
<Button disabled>Primary</Button>
<Button variant="secondary" disabled>
Secondary
</Button>
</div>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'secondary' | 'ghost' | 'danger' | 'primary' | Visual style: primary / secondary / ghost / danger |
size | 'sm' | 'md' | 'lg' | 'md' | Control size: sm / md / lg |
loading | boolean | false | Shows a spinner, disables the button and sets aria-busy |
leadingIcon | ReactNode | — | Icon before the label, scales with the font size; yields to the spinner while loading |
trailingIcon | ReactNode | — | Icon after the label, scales with the font size; hidden while loading |
iconOnly | boolean | false | Icon-only button: drops the horizontal padding and becomes square; provide an aria-label |
circle | boolean | false | Circle button: square with a full radius, ideal for icons; provide an aria-label |
children | ReactNode | — | Button content |
...rest | ButtonHTMLAttributes | — | Remaining props are forwarded to the native button |