useOverlay
Usage
Use the auto-imported useOverlay
composable to programmatically control Modal and Slideover components.
<script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay()
const modal = overlay.create(LazyModalExample)
async function openModal() {
modal.open()
}
</script>
- The
useOverlay
composable is created usingcreateSharedComposable
, ensuring that the same overlay state is shared across your entire application.
overlay.open()
can be awaited. In order for this to work, however, the overlay component must emit a close
event. See 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): OverlayInstance
Create an overlay, and return a factory instance.
Parameters
false
.false
.on()
on(event: string, callback: (value: unknown) => void): void
Parameters
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
patch()
patch(id: symbol, props: 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
on()
on(event: string, callback: (value: unknown) => void): void
Listen to overlay's component emits.
Parameters
<script setup lang="ts">
import { LazyModalExample } from '#components'
const overlay = useOverlay()
const modal = overlay.create(LazyModalExample)
modal.on('event-emitted', () => {
console.log('event emitted')
})
function openModal() {
modal.open({
title: 'Welcome'
})
}
</script>
open()
open(props?: ComponentProps<T>): Promise<OpenedOverlay<T>>
Open the overlay.
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: 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, {
title: 'Welcome'
})
function openModal() {
modal.open()
}
function updateModalTitle() {
modal.patch({ title: 'Updated Title' })
}
</script>
Example
Here's a complete example of how to use the useOverlay
composable:
<script setup lang="ts">
import { ModalA, ModalB, SlideoverA } from '#components'
const overlay = useOverlay()
// Create with default props
const modalA = overlay.create(ModalA, { title: 'Welcome' })
const modalB = overlay.create(ModalB)
const slideoverA = overlay.create(SlideoverA)
modalA.on('close', (value) => {
console.log(value)
})
const openModalA = () => {
// Open modalA, but override the title prop
modalA.open({ title: 'Hello' })
}
const openModalB = async () => {
// Open modalB
const modalBInstance = modalB.open()
/// Open the slideover when modalB closes
/// - Using the callback argument of the `on` method
modalB.on('close', (input) => {
slideoverA.open({ input })
})
/// - Using the promise returned by `open`
// Wait for opening result (resolved automatically when the overlay is closed)
const input = await modalBInstance
// Pass the result from modalB to the slideover, and open it
slideoverA.open({ input })
}
</script>
<template>
<button @click="openModalA">Open Modal</button>
</template>
In this example, we're using the useOverlay
composable to control multiple modals and slideovers.
Caveats
Provide / Inject
When opening overlays programmatically (e.g. modals, slideovers, etc), the overlay component can only access injected values from the component containing UApp
(typically app.vue
or layout components). This is because overlays are mounted outside of the page context by the UApp
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 providedValue = inject('valueProvidedInPage')
const modal = overlay.create(LazyModalExample, {
props: {
providedValue,
otherData: someValue
}
})
</script>
Limitation for components with more than 5 emits
Because of TypeScript limitation for infer overloaded functions in conditional types (cf: https://github.com/microsoft/TypeScript/issues/32164).
Because of this limitation, you could expect typing issues for components with more than 5 defined emits. This limitation is set 5 as we use a trick to make work for most cases.