Appearance
Dialog
Asks for a small task or an answer before the user goes on: a short form, a short edit, a confirmation.
vue
<script setup lang="ts">
import { FsButton, FsDialog, FsField, FsInput } from '@fivespark/ui'
import { ref } from 'vue'
const name = ref('')
</script>
<template>
<div class="grid min-h-[28rem] place-items-center">
<FsDialog title="Klant toevoegen">
<template #trigger="{ props }">
<FsButton v-bind="props" label="Klant toevoegen" />
</template>
<FsField label="Bedrijfsnaam"><FsInput v-model="name" autofocus /></FsField>
<template #footer="{ close }">
<FsButton label="Annuleren" @click="close" />
<FsButton variant="primary" label="Toevoegen" @click="close" />
</template>
</FsDialog>
</div>
</template>Usage
vue
<script setup lang="ts">
import { FsButton, FsDialog } from '@fivespark/ui'
</script>
<template>
<FsDialog title="Klant toevoegen">
<template #trigger="{ props }">
<FsButton v-bind="props" label="Klant toevoegen" />
</template>
…
<template #footer="{ close }">
<FsButton label="Annuleren" @click="close" />
</template>
</FsDialog>
</template>A dialog blocks the page and closes only by Esc, its close button or its own buttons. For a panel beside a list, use a Drawer; for something a click beside it may dismiss, a Popover.
Examples
Confirmation
With alert, the dialog is announced as an alert and needs a description that says what happens and to what. Put autofocus on the least destructive button.
vue
<script setup lang="ts">
import { FsButton, FsDialog } from '@fivespark/ui'
</script>
<template>
<div class="grid min-h-[28rem] place-items-center">
<FsDialog alert title="Offerte verwijderen?" description="Offerte OF-2026-014 voor Jansen Bouw B.V. wordt verwijderd. Dit kan niet ongedaan worden.">
<template #trigger="{ props }">
<FsButton v-bind="props" variant="destructive" label="Offerte verwijderen" />
</template>
<template #footer="{ close }">
<FsButton label="Annuleren" autofocus @click="close" />
<FsButton variant="destructive" label="Verwijderen" @click="close" />
</template>
</FsDialog>
</div>
</template>With a description
The description is read out with the title and shown above the content.
vue
<script setup lang="ts">
import { FsButton, FsDialog, FsField, FsInput } from '@fivespark/ui'
import { ref } from 'vue'
const email = ref('')
</script>
<template>
<div class="grid min-h-[28rem] place-items-center">
<FsDialog title="Offerte versturen" description="De offerte gaat als pdf naar dit e-mailadres.">
<template #trigger="{ props }">
<FsButton v-bind="props" label="Offerte versturen" />
</template>
<FsField label="E-mailadres"><FsInput v-model="email" type="email" autofocus /></FsField>
<template #footer="{ close }">
<FsButton label="Annuleren" @click="close" />
<FsButton variant="primary" label="Versturen" @click="close" />
</template>
</FsDialog>
</div>
</template>Controlled with v-model
Without a trigger, open it from anywhere with v-model:open. It is set to false however the dialog closes.
vue
<script setup lang="ts">
import { FsButton, FsDialog } from '@fivespark/ui'
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<div class="grid min-h-[28rem] place-items-center">
<FsButton label="Planning bevestigen" @click="open = true" />
<FsDialog v-model:open="open" title="Planning bevestigen" description="De monteurs krijgen de planning van volgende week in hun app.">
<template #footer="{ close }">
<FsButton label="Annuleren" @click="close" />
<FsButton variant="primary" label="Bevestigen" @click="close" />
</template>
</FsDialog>
</div>
</template>Keep the dialog mounted and close it through open; removing it with v-if while open skips the focus return. Place it outside any <form>.
Keyboard
| Key | Does |
|---|---|
| Esc | Closes the dialog, an alert too. A popover or select open inside it takes the key first |
| Tab, Shift + Tab | Moves between the controls inside; focus stays in the dialog |
| Enter, Space | On the trigger, opens the dialog; on the close button, closes it |
API Reference
FsDialog
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | required | Shown at the top as a heading, and names the dialog. |
description | string | One or two sentences at the top of the body, read out with the name. Required with `alert`: it is the question's message. | |
alert | boolean | false | A confirmation: announced as an alert dialog. |
open | boolean | false | True while the dialog shows, however it was opened. Set it to open or close the dialog. |
| Event | Payload | Description |
|---|---|---|
update:open | [value: boolean] | Sent with the new `open`, for `v-model:open`. |
| Slot | Props | Description |
|---|---|---|
trigger | { props: Record<string, unknown>; } | The button that opens it: bind `props` on it, `<FsButton v-bind="props" label="Klant toevoegen" />`. Focus returns to it on close. |
default | { close: () => void; } | The body, below the description. `close()` closes the dialog. |
footer | { close: () => void; } | The actions, at the end. `close()` closes the dialog, for a Cancel button. |