Usage
Use the auto-imported useOverlay composable to programmatically control Modal and Slideover components.
- The
useOverlaycomposable is created usingcreateSharedComposable, ensuring that the same overlay state is shared across your entire application.
overlay.open() to get a value back from the overlay. This only works if the overlay component emits a close event. See the example below for details.API
useOverlay()
The useOverlay composable provides methods to manage overlays globally. Each created overlay returns an instance with its own methods.
create()
create(component: T, options?: OverlayOptions<ComponentProps<T>>): OverlayInstance<T>
Create an overlay, and return a factory instance.
Parameters
false.false.open()
open(id: symbol, props?: ComponentProps<T>): OpenedOverlay<T>
Open an overlay by its id.
Parameters
close()
close(id: symbol, value?: any): void
Close an overlay by its id.
Parameters
closeAll()
closeAll(): void
Close all open overlays.
patch()
patch(id: symbol, props: Partial<ComponentProps<T>>): void
Update an overlay by its id.
Parameters
unmount()
unmount(id: symbol): void
Remove an overlay from the DOM by its id.
Parameters
isOpen()
isOpen(id: symbol): boolean
Check if an overlay is open using its id.
Parameters
overlays
overlays: Overlay[]
In-memory list of all overlays that were created.
Instance API
These are the methods available on the instance returned by create().
open()
open(props?: ComponentProps<T>): OpenedOverlay<T>
Open the overlay. Returns an OpenedOverlay, a Promise that resolves with the value emitted by the close event. The same promise is also exposed as result, so const { result } = modal.open() works too.
Parameters
<script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay()
const modal = overlay.create(LazyModalExample)
function openModal() {
modal.open({
title: 'Welcome'
})
}
</script>
close()
close(value?: any): void
Close the overlay.
Parameters
patch()
patch(props: Partial<ComponentProps<T>>): void
Update the props of the overlay.
Parameters
<script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay()
const modal = overlay.create(LazyModalExample, {
props: { title: 'Welcome' }
})
function openModal() {
modal.open()
}
function updateModalTitle() {
modal.patch({ title: 'Updated Title' })
}
</script>
Examples
With multiple overlays
This example demonstrates how to manage multiple overlays and pass data between them:
<script setup lang="ts">
import { ModalA, ModalB, SlideoverA } from '#components'
const overlay = useOverlay()
// Create with default props
const modalA = overlay.create(ModalA, { props: { title: 'Welcome' } })
const modalB = overlay.create(ModalB)
const slideoverA = overlay.create(SlideoverA)
const openModalA = () => {
// Open modalA, but override the title prop
modalA.open({ title: 'Hello' })
}
const openModalB = async () => {
// Open modalB, and wait for its result
const input = await modalB.open()
// Pass the result from modalB to the slideover, and open it
slideoverA.open({ input })
}
</script>
<template>
<B24Button label="Open Modal" @click="openModalA" />
</template>
Confirm dialog
This example demonstrates how to create a reusable confirm dialog pattern using a custom useConfirmDialog composable that wraps useOverlay. This approach enables opinionated dialogs tailored to specific business requirements and design preferences.
- Create a
ConfirmDialogcomponent that emits a boolean value when closed:
<script lang="ts" setup>
interface ConfirmDialogProps {
title?: string
description?: string
}
defineProps<ConfirmDialogProps>()
const emits = defineEmits<{
close: [value: boolean]
}>()
</script>
<template>
<B24Modal
:title="title"
:description="description"
:dismissible="false"
:b24ui="{ footer: 'justify-end' }"
>
<template #footer>
<B24Button label="Cancel" @click="emits('close', false)" />
<B24Button label="Confirm" @click="emits('close', true)" />
</template>
</B24Modal>
</template>
- Create a
useConfirmDialogcomposable that returns a Promise:
import { ConfirmDialog } from '#components'
export interface ConfirmDialogOptions {
title: string
description?: string
}
export const useConfirmDialog = () => {
const overlay = useOverlay()
return (options: ConfirmDialogOptions): Promise<boolean> => {
const modal = overlay.create(ConfirmDialog, {
destroyOnClose: true,
props: options
})
return modal.open()
}
}
- Use the composable in your components:
<script setup lang="ts">
const confirm = useConfirmDialog()
const handleDelete = async () => {
const confirmed = await confirm({
title: 'Delete item',
description: 'Are you sure you want to delete this item?'
})
if (confirmed) {
console.log('Item deleted')
}
}
</script>
<template>
<B24Button label="Delete item" @click="handleDelete" />
</template>
Caveats
Provide / Inject
When opening overlays programmatically (e.g. modals, slideovers, etc), the overlay component can only access injected values from the component containing B24App (typically app.vue or layout components). This is because overlays are mounted outside of the page context by the B24App component.
As such, using provide() in pages or parent components isn't supported directly. To pass provided values to overlays, the recommended approach is to use props instead:
<script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay()
const providedValue = inject('valueProvidedInPage')
const modal = overlay.create(LazyModalExample, {
props: {
providedValue
}
})
</script>