Buttons
Elevated interactive elements that provide tactile feedback via scale and shadow compression on click.
Physics Buttons use convex shadows (drop shadows) to create depth. On hover, shadow spreads and lifts. On active/press, shadow compresses and element translates down, simulating physical button press.
Button Sizes
xs (24px), sm (30px), md (36px, default), lg (42px), xl (48px)Buttons with Icons
leftIcon or rightIcon: the slot spaces them from the label by the size's gap (4px at sm, 8px at md and lg).Error State
Error-Disabled State: Used when a button action is blocked by validation errors or missing required data. Pass error with disabled: the button takes the error colors (a red tint, border and label) in place of its own and fades like any disabled button. Like Disabled, it takes no hover, press or click. The library doesn't render the error text, so name the problem next to the field that has it. On its own, error leaves the button enabled.
// Validation errors block the action.
<Button variant="primary" error disabled>
Submit Form
</Button>Best Practices
Do
Use primary for main action, secondary for cancel/dismiss
Use icons alongside text for clarity
Use ghost variant for icon-only utility buttons
Don't
Don't use multiple primary buttons in the same context
Don't use icon-only buttons with low-contrast variants
Don't use overly verbose button text
Examples
<Button variant="primary">Save Changes</Button><Button variant="primary" leftIcon={<Icon name="check" size="sm" />}>
Complete Order
</Button><Button variant="ghost" iconOnly leftIcon={<Icon name="menu" size="sm" />} />Icon-Only Buttons
Use the iconOnly prop for square buttons that contain only an icon. This applies proper padding for a balanced appearance.
// Icon-only buttons with different sizes.
// leftIcon takes a ReactNode: a gloss-icons <Icon>, or an SVG of your own.
<Button variant="primary" size="sm" iconOnly leftIcon={<Icon name="plus" size="sm" />} />
<Button variant="primary" iconOnly leftIcon={<Icon name="plus" size="sm" />} />
<Button variant="primary" size="lg" iconOnly leftIcon={<Icon name="plus" size="md" />} />
// Different variants
<Button variant="secondary" iconOnly leftIcon={<SettingsIcon />} />
<Button variant="ghost" iconOnly leftIcon={<Icon name="more-vertical" size="sm" />} />ButtonGroup
Group related buttons together with consistent spacing or attached styling. ButtonGroup can propagate size and variant to child buttons via context.
<ButtonGroup>
<Button variant="secondary">Day</Button>
<Button variant="secondary">Week</Button>
<Button variant="secondary">Month</Button>
<Button variant="secondary">Year</Button>
</ButtonGroup><ButtonGroup attached>
<Button variant="secondary">Left</Button>
<Button variant="secondary">Center</Button>
<Button variant="secondary">Right</Button>
</ButtonGroup><ButtonGroup orientation="vertical" attached>
<Button variant="secondary" leftIcon={<ListIcon />}>List View</Button>
<Button variant="secondary" leftIcon={<GridIcon />}>Grid View</Button>
<Button variant="secondary" leftIcon={<ColumnsIcon />}>Column View</Button>
</ButtonGroup><ButtonGroup fullWidth attached>
<Button variant="secondary">Cancel</Button>
<Button variant="primary">Confirm</Button>
</ButtonGroup>SplitButton
A split button combines a primary action with a dropdown menu for secondary actions. The main button handles the default action while the dropdown provides alternatives.
<SplitButton
onClick={() => handleSave()}
menuItems={[
{ label: 'Save as draft', onClick: () => handleSaveDraft() },
{ label: 'Save and publish', onClick: () => handlePublish() },
{ label: 'Save as template', onClick: () => handleTemplate() },
]}
>
Save
</SplitButton><SplitButton
leftIcon={<DownloadIcon />}
onClick={() => handleDownload()}
menuItems={[
{ label: 'Download PDF', onClick: handlePDF, icon: <FileIcon /> },
{ label: 'Download CSV', onClick: handleCSV, icon: <FileIcon /> },
{ divider: true, label: 'Email report', onClick: handleEmail, icon: <MailIcon /> },
]}
>
Download
</SplitButton>// Primary variant, small size
<SplitButton variant="primary" size="sm" menuItems={[...]}>
Primary Small
</SplitButton>
// Secondary variant, default size
<SplitButton variant="secondary" menuItems={[...]}>
Secondary Default
</SplitButton>
// Ghost variant, large size
<SplitButton variant="ghost" size="lg" menuItems={[...]}>
Ghost Large
</SplitButton>Props Reference
Button| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'primary' | 'secondary' | 'ghost' | 'outline' | 'destructive' | 'primary' | Visual style variant |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Button size (24, 30, 36, 42, 48px) |
disabled | boolean | false | Disable the button |
isLoading | boolean | false | Show loading spinner |
iconOnly | boolean | false | Square button for icon-only content |
leftIcon | ReactNode | — | Icon before button text |
rightIcon | ReactNode | — | Icon after button text |
error | string | boolean | — | With disabled, shows the error-disabled state; on its own, leaves the button enabled |
ButtonGroup| Prop | Type | Default | Description |
|---|---|---|---|
orientation | 'horizontal' | 'vertical' | 'horizontal' | Layout direction |
attached | boolean | false | Connect buttons visually (no gaps, merged borders) |
size | 'sm' | 'md' | 'lg' | — | Size applied to all child buttons |
variant | ButtonVariant | — | Variant applied to all child buttons |
fullWidth | boolean | false | Buttons share available space equally |
gap | 'none' | 'sm' | 'md' | 'lg' | 'md' | Gap between buttons (when not attached) |
SplitButton| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Required | Main button content |
onClick | () => void | — | Main button click handler |
menuItems | SplitButtonMenuItem[] | Required | Dropdown menu items |
variant | 'primary' | 'secondary' | 'ghost' | 'outline' | 'destructive' | 'primary' | Button style variant |
size | 'sm' | 'md' | 'lg' | 'md' | Button size |
disabled | boolean | false | Disable both buttons |
leftIcon | ReactNode | — | Icon for main button |
dropdownIcon | ReactNode | Built-in chevron | Icon for dropdown trigger |
SplitButtonMenuItem| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | Required | Menu item text |
onClick | () => void | Required | Click handler |
icon | string | ReactNode | — | Optional icon |
disabled | boolean | — | Disabled state |
divider | boolean | — | Show divider before this item |