Skip to content

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>
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 ​

KeyDoes
Enter, SpacePresses the button, unless it is disabled or loading

API Reference ​

FsButton ​

PropTypeDefaultDescription
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.
labelstringThe 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.
loadingbooleanBlocks 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.
loadingTextstringAnnounced when loading starts: "Laden…" or "Loading…" unless given. Say what is happening: "Offerte opslaan…".
disabledbooleanfalseUnavailable for now: still focusable and announced, its presses blocked. Put the reason beside it. Not for a submit button.
blockbooleanfalseFull width, the label centred.
tostring | objectNavigates, through the app's link component or a plain `<a>`. A route object needs a link component.
hrefstringNavigates with a plain `<a>`: another site, or a file.
newTabbooleanfalseOpens a new tab, with an icon and hidden text that say so. Only with `to` or `href`.
newTabTextstringReplaces the hidden new-tab text, "(opent in een nieuwe tab)" or "(opens in a new tab)".
EventPayloadDescription
click[event: MouseEvent]A press. Not emitted while disabled or loading.
SlotPropsDescription
leadinganyIn place of `leadingIcon`: anything before the label.
defaultanyThe text, in place of `label`: for a label with markup in it.
trailinganyIn place of `trailingIcon`: anything after the label.