Skip to content

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 ​

KeyDoes
EscCloses the dialog, an alert too. A popover or select open inside it takes the key first
Tab, Shift + TabMoves between the controls inside; focus stays in the dialog
Enter, SpaceOn the trigger, opens the dialog; on the close button, closes it

API Reference ​

FsDialog ​

PropTypeDefaultDescription
titlestringrequiredShown at the top as a heading, and names the dialog.
descriptionstringOne or two sentences at the top of the body, read out with the name. Required with `alert`: it is the question's message.
alertbooleanfalseA confirmation: announced as an alert dialog.
openbooleanfalseTrue while the dialog shows, however it was opened. Set it to open or close the dialog.
EventPayloadDescription
update:open[value: boolean]Sent with the new `open`, for `v-model:open`.
SlotPropsDescription
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.