Skip to content

useModal

Open a modal programmatically from anywhere.

useModal() lets you open a <SModal> (or any component you point it at) without placing it in your template - useful for confirmation dialogs triggered from a click handler, or flows where the modal's content isn't known until runtime.

Usage

vue
<script setup lang="ts">
const { open } = useModal()
const modal = useTemplateRef('confirmModal')

async function handleDelete() {
  const confirmed = await open(ConfirmDeleteDialog, {
    props: { itemName: 'My project' },
  })
  if (confirmed) {
    // ...
  }
}
</script>

The component you pass to open() resolves the returned promise by emitting close with its result. Escape, an outside click, or the shell's close button resolve it with undefined.

API

ts
function useModal(): {
  open: <T = void>(component: Component, options?: UseModalOpenOptions) => Promise<T | undefined>
}

open() resolves with undefined if the modal is dismissed without an explicit value (e.g. Escape, backdrop click).

UseModalOpenOptions

OptionTypeDescription
propsRecord<string, unknown>Props passed to the opened component.
titlestringRegistered with Reka as the dialog's accessible name, visually hidden - the opened component still supplies its own visible header via the content slot.
descriptionstringRegistered with Reka as the dialog's accessible description, visually hidden.
dismissiblebooleanWhether Escape/backdrop click closes it.
modalbooleanWhether it traps focus and blocks interaction outside.
overlaybooleanWhether a backdrop is rendered.
transitionbooleanWhether the open/close animation plays.

Every option is forwarded straight through to the underlying SModal instance, and defaults to SModal's own defaults when omitted. Since the opened component always renders through SModal's content slot (see Modal), title/description are the only way to give a programmatically-opened dialog a real accessible name/description - pass them if the opened component's own content doesn't already include a heading Reka can associate with it.

Setup

The render loop that actually mounts opened modals lives inside <SApp> - wrap your app's root with it once (typically in app.vue) and useModal() works anywhere underneath:

vue-html
<SApp>
  <NuxtPage />
</SApp>
Edit this page