Appearance
Button
Starts an action on the current page: save, send, cancel, open a menu or a dialog.
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<FsButton variant="primary" label="Offerte versturen" />
</template>Usage
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<FsButton label="Opslaan" @click="save" />
</template>A button that goes somewhere else is a link: give it to or href and it renders one. A button that stays pressed is Toggle.
Examples
Variants
Secondary is the default. Primary, in yellow, is the one main action of a page or a dialog; destructive is for an action that removes something.
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<div class="flex flex-wrap gap-2">
<FsButton variant="primary" label="Offerte versturen" />
<FsButton label="Opslaan als concept" />
<FsButton variant="ghost" label="Annuleren" />
<FsButton variant="destructive" label="Offerte verwijderen" />
</div>
</template>Sizes
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<div class="flex flex-wrap items-center gap-2">
<FsButton label="Opslaan" />
<FsButton size="dense" label="Opslaan" />
</div>
</template>With icons
A trailing chevron-down says the button opens a menu.
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<div class="flex flex-wrap gap-2">
<FsButton label="Exporteren" leading-icon="download" />
<FsButton label="Opties" trailing-icon="chevron-down" />
</div>
</template>Icon only
label becomes the button's name, read by screen readers and shown in a tooltip.
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<div class="flex flex-wrap gap-2">
<FsButton icon="plus" label="Regel toevoegen" />
<FsButton variant="ghost" icon="pencil" label="Regel bewerken" />
</div>
</template>Disabled
A disabled button stays focusable, so put the reason beside it and point to it with aria-describedby.
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<div class="flex flex-col items-start gap-2">
<FsButton variant="primary" label="Offerte versturen" disabled aria-describedby="send-reason" />
<p id="send-reason" class="type-meta text-text-muted">Voeg eerst een regel toe.</p>
</div>
</template>Loading
Presses are blocked at once; the spinner shows after a second, and loadingText is announced.
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
import { ref } from 'vue'
const saving = ref(false)
function save() {
saving.value = true
setTimeout(() => (saving.value = false), 3000)
}
</script>
<template>
<FsButton variant="primary" label="Opslaan" loading-text="Offerte opslaan…" :loading="saving" @click="save" />
</template>As a link
vue
<script setup lang="ts">
import { FsButton } from '@fivespark/ui'
</script>
<template>
<div class="flex flex-wrap gap-2">
<FsButton label="Naar offertes" to="/offertes" />
<FsButton label="Handleiding" href="https://www.fivespark.com/" new-tab />
</div>
</template>Keyboard
| Key | Does |
|---|---|
| Enter, Space | Presses the button, unless it is disabled or loading |
API Reference
FsButton
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "primary" | "secondary" | "ghost" | "destructive" | "secondary" | `primary` for the one action that commits, `ghost` in toolbars and table rows, `destructive` to confirm a deletion. |
size | "default" | "dense" | "default" | `default` is 36px high; `dense` is 32px, for tables and toolbars. |
type | "button" | "submit" | "reset" | "button" | `button` unless asked, so a button in a form never submits by accident. |
label | string | The visible text, or the hidden name of an icon-only button. Needed when there is no default slot. | |
icon | "info" | "plus" | "pencil" | "trash" | "copy" | "x" | "download" | "upload" | "search" | "funnel" | "check" | "minus" | "external-link" | "eye" | "eye-off" | "settings" | "log-out" | "ellipsis" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-left" | "arrow-right" | "arrow-up" | "arrow-down" | "arrow-up-down" | "layout-dashboard" | "menu" | "circle-check" | "circle-x" | "triangle-alert" | "circle-question-mark" | "loader-circle" | "calculator" | "file-text" | "user" | "building" | "package" | "truck" | "euro" | "percent" | "clock" | "calendar" | "database" | "chart-column" | Makes the button icon-only and square: this icon, with `label` as its hidden name. | |
leadingIcon | "info" | "plus" | "pencil" | "trash" | "copy" | "x" | "download" | "upload" | "search" | "funnel" | "check" | "minus" | "external-link" | "eye" | "eye-off" | "settings" | "log-out" | "ellipsis" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-left" | "arrow-right" | "arrow-up" | "arrow-down" | "arrow-up-down" | "layout-dashboard" | "menu" | "circle-check" | "circle-x" | "triangle-alert" | "circle-question-mark" | "loader-circle" | "calculator" | "file-text" | "user" | "building" | "package" | "truck" | "euro" | "percent" | "clock" | "calendar" | "database" | "chart-column" | An icon before the label. | |
trailingIcon | "info" | "plus" | "pencil" | "trash" | "copy" | "x" | "download" | "upload" | "search" | "funnel" | "check" | "minus" | "external-link" | "eye" | "eye-off" | "settings" | "log-out" | "ellipsis" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-left" | "arrow-right" | "arrow-up" | "arrow-down" | "arrow-up-down" | "layout-dashboard" | "menu" | "circle-check" | "circle-x" | "triangle-alert" | "circle-question-mark" | "loader-circle" | "calculator" | "file-text" | "user" | "building" | "package" | "truck" | "euro" | "percent" | "clock" | "calendar" | "database" | "chart-column" | An icon after the label. `chevron-down` means the button opens a menu. | |
loading | boolean | Blocks presses at once, and covers the label with a spinner after about a second. Pass it, even as `false`, on a button that will load, so its announcement is ready before it starts. | |
loadingText | string | Announced when loading starts: "Laden…" or "Loading…" unless given. Say what is happening: "Offerte opslaan…". | |
disabled | boolean | false | Unavailable for now: still focusable and announced, its presses blocked. Put the reason beside it. Not for a submit button. |
block | boolean | false | Full width, the label centred. |
to | string | object | Navigates, through the app's link component or a plain `<a>`. A route object needs a link component. | |
href | string | Navigates with a plain `<a>`: another site, or a file. | |
newTab | boolean | false | Opens a new tab, with an icon and hidden text that say so. Only with `to` or `href`. |
newTabText | string | Replaces the hidden new-tab text, "(opent in een nieuwe tab)" or "(opens in a new tab)". |
| Event | Payload | Description |
|---|---|---|
click | [event: MouseEvent] | A press. Not emitted while disabled or loading. |
| Slot | Props | Description |
|---|---|---|
leading | any | In place of `leadingIcon`: anything before the label. |
default | any | The text, in place of `label`: for a label with markup in it. |
trailing | any | In place of `trailingIcon`: anything after the label. |