Button
Buttons trigger actions or events. The Davis Button component provides semantic variants, multiple sizes, loading states, and full keyboard accessibility.
Installation
npm install @libretexts/davis-react
Basic Usage
import { Button } from '@libretexts/davis-react';
export default function Example() {
return <Button>Click me</Button>;
}
Variants
Buttons come in seven semantic variants to communicate different action types.
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="warning">Warning</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="outline">Outline</Button>
When to use each variant:
- Primary - Main call-to-action (e.g., "Save", "Submit", "Continue")
- Secondary - Secondary actions (e.g., "Cancel", "Back")
- Tertiary - Tertiary actions, less emphasis than secondary
- Destructive - Irreversible destructive actions (e.g., "Delete", "Remove")
- Warning - Caution actions (e.g., "Archive", "Suspend")
- Ghost - Subtle actions, minimal visual weight
- Outline - Alternative style with border emphasis
Sizes
Buttons are available in three sizes to match your design hierarchy.
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
Full Width
Make buttons span the full width of their container.
<Button fullWidth>Full Width Button</Button>
Loading State
Show a spinner while async actions are in progress. Buttons are automatically disabled when loading.
import { Button } from '@libretexts/davis-react';
import { useState } from 'react';
export default function Example() {
const [loading, setLoading] = useState(false);
async function handleClick() {
setLoading(true);
await fetch('/api/save');
setLoading(false);
}
return (
<Button loading={loading} onClick={handleClick}>
Save Changes
</Button>
);
}
With Icons
Add icons to buttons to enhance clarity and scannability.
import { Button } from '@libretexts/davis-react';
function SaveIcon() {
return (
<svg className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
</svg>
);
}
export default function Example() {
return (
<>
<Button icon={<SaveIcon />} iconPosition="left">
Save
</Button>
<Button icon={<SaveIcon />} iconPosition="right">
Continue
</Button>
</>
);
}
As Link
Render a button as a link element while maintaining button styling.
<Button as="a" href="/dashboard">
Go to Dashboard
</Button>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'warning' | 'ghost' | 'outline' | 'primary' | Visual style variant |
size | 'sm' | 'md' | 'lg' | 'md' | Button size |
loading | boolean | false | Show loading spinner and disable button |
disabled | boolean | false | Disable button |
fullWidth | boolean | false | Make button full width |
icon | ReactNode | - | Icon element to display |
iconPosition | 'left' | 'right' | 'left' | Position of icon |
as | ElementType | 'button' | Render as different element (e.g., 'a') |
Accessibility
The Button component is built with accessibility in mind:
- Uses semantic
<button>element by default - Properly handles disabled and loading states
- Loading state includes
aria-busy="true" - Disabled state includes
aria-disabled="true"anddisabledattribute - Keyboard accessible (Space and Enter keys)
- Focus visible with clear focus rings
Best practices:
- Always provide descriptive button text
- For icon-only buttons, use
aria-label - Use appropriate variants to communicate action type
- Don't nest interactive elements inside buttons