Button
Starts an action, or goes somewhere when it has a link. Six variants in any colour of the theme, sizes on the golden scale, and a loading state that keeps focus.
Usage
A Button is a <button type="button">, so it never submits a form by accident;
pass type="submit" for the one that should. Every attribute you give it reaches the element.
<script>
import { Button } from 'sveltier';
</script>
<Button onclick={() => (open = true)}>New transfer</Button>
<Button variant="outlined" color="error">Cancel payment</Button>Variants and colours
elevated sets the colour on a raised surface, flat fills with it, tonal tints with it, outlined adds a border, text is the colour alone, and plain has no hover or press wash. Every pairing meets WCAG AA contrast in all five theme
packs, light and dark.
Size and density
size moves the height half a step of φ and the text a quarter step; density tightens or loosens height and padding without touching the text. See Shared props.
Icons
prepend and append put content before and after the label. Icons are
sized to φ^½ of the text. With icon, the button is square and holds only its icon,
so give it an aria-label.
<Button>
{#snippet prepend()}<PlusIcon />{/snippet}
New transfer
</Button>
<!-- An icon alone needs a label for screen readers. -->
<Button icon variant="text" aria-label="Close"><CloseIcon /></Button>Loading and disabled
loading shows a spinner over the label and ignores presses, while the button keeps its
size and focus. Screen readers hear that it is loading. A disabled button cannot be focused or pressed.
Nothing paid yet. Press Pay invoice twice quickly: the second press is ignored while it loads.
<script>
import { Button } from 'sveltier';
let paying = $state(false);
async function pay() {
paying = true;
try {
await payInvoice();
} finally {
paying = false;
}
}
</script>
<!-- Ignores presses while loading, so the invoice is paid once. -->
<Button loading={paying} onclick={pay}>Pay invoice</Button>Links
With href, the Button is an <a>: it navigates, opens in a new
tab and works with your router like any link. A disabled link drops its href.
<!-- href makes it a link: middle-click, open in a new tab and
client-side navigation work as they do for any link. -->
<Button href="/statements" variant="tonal">Statements</Button>Defaults
Set Button props for a whole app or section with defaults on UIProvider or a DefaultsProvider. A prop on the Button itself still wins.
<UIProvider
themes={monolith}
defaults={{ Button: { variant: 'tonal', rounded: 'full' } }}
>
<!-- Every Button below is tonal and round unless it says otherwise. -->
</UIProvider>Accessibility
- Enter and Space press a button; Enter follows a link. Both are reached with Tab.
- Disabled buttons use the native
disabledattribute and leave the tab order. A loading button stays focusable and is markedaria-disabled; you can do the same for a button that should stay discoverable while unavailable. - An icon button needs
aria-labeloraria-labelledby. - Hover and press are shown with a tint and a one-pixel press, and reduced motion keeps it still.
API
| Name | Type | Default | Description |
|---|---|---|---|
variant | 'elevated' | 'flat' | 'tonal' | 'outlined' | 'text' | 'plain' | 'flat' | Visual weight. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Height and text size. |
density | 'compact' | 'default' | 'comfortable' | 'default' | Multiplies the height and padding, never the text. |
color | Color | 'primary' | The colour the variant is painted with. |
rounded | boolean | 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | true | Corner rounding. true keeps the theme's radius. |
block | boolean | false | Takes the full width of its container. |
disabled | boolean | false | A disabled button cannot be focused or pressed; a disabled link loses its href. |
as | 'button' | 'a' | – | The element to render. Defaults to 'a' when href is given, otherwise 'button'. |
icon | boolean | false | Square, for a single icon as the content. Give it an aria-label. |
loading | boolean | false | Shows a spinner and ignores presses, while the button keeps focus and its label for screen readers, which also hear that it is loading. |
prepend | Snippet | – | Content before the label, usually an icon. |
append | Snippet | – | Content after the label, usually an icon. |
children | Snippet | – | The label. |
class | ClassValue | null | – | Classes added after the component's own: a string, an array or an object. |
ref | HTMLButtonElement | HTMLAnchorElement | null | – | The root element, bindable with bind:ref. |