Components
Button
Triggers an action or navigates to a new page.
Overview
Buttons communicate actions users can take. Use primary for the main action, secondary for alternatives, and destructive for irreversible actions. The Button component supports both button and link roles.
Variants
Six visual variants are available:
| Variant | Usage |
|---|---|
primary | Main call-to-action (dark background, white text) |
secondary | Alternative actions (outlined, subtle background) |
secondary-alt | Alternative with subtle fill instead of border |
ghost | Text-only, minimal footprint |
destructive | Irreversible or dangerous actions (red tinted) |
link | Inline link-style button (brand color) |
import { Button } from '@fsai/shared-ui';
<Button role="button" variant="primary">Submit</Button>
<Button role="button" variant="secondary">Cancel</Button>
<Button role="button" variant="secondary-alt">Alternative</Button>
<Button role="button" variant="ghost">Ghost</Button>
<Button role="button" variant="destructive">Delete</Button>
<Button role="button" variant="link">Learn more</Button>Sizes
Four sizes are available. Default is md.
| Size | Height | Usage |
|---|---|---|
lg | 48px | Hero sections, prominent CTAs |
md | 36px | Standard actions (default) |
sm | 32px | Compact toolbars, table rows |
xs | 28px | Inline actions, tight spaces |
<Button role="button" size="lg">Large</Button>
<Button role="button" size="md">Medium</Button>
<Button role="button" size="sm">Small</Button>
<Button role="button" size="xs">Extra Small</Button>With Icons
Use leftAdornment or rightAdornment to add icons from @fsai/icons:
<Button role="button" leftAdornment="Plus">Add Item</Button>
<Button role="button" rightAdornment="ChevronRightSmall">Next</Button>Loading State
Set isLoading to show a spinner and disable interaction:
<Button role="button" isLoading>Saving...</Button>Link Role
Use role="link" to render as a navigation link (uses react-router-dom Link):
<Button role="link" href="/settings">Go to Settings</Button>
<Button role="link" href="https://example.com" external>External Link</Button>Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'secondary' | 'secondary-alt' | 'ghost' | 'destructive' | 'link' | 'primary' | Visual style |
size | 'lg' | 'md' | 'sm' | 'xs' | 'md' | Size of the button |
role | 'button' | 'link' | — | Required. Determines behavior |
isLoading | boolean | false | Shows spinner, disables interaction |
isActive | boolean | false | Shows active/pressed visual state |
leftAdornment | IconName | — | Icon before the label |
rightAdornment | IconName | — | Icon after the label |
disabled | boolean | false | Disables the button (button role only) |
onClick | (event: MouseEvent) => void | — | Click handler (button role only) |
href | string | — | Navigation target (link role only) |
external | boolean | false | Opens in new tab (link role only) |
Guidelines
- Do use a single primary button per section for the main action
- Do use descriptive labels ("Save changes" not "OK")
- Do use
isLoadingduring async operations to prevent double-clicks - Don't use destructive variant for non-destructive actions
- Don't disable buttons without explaining why (use a Tooltip)
- Don't use the ghost variant for primary actions — it's too subtle