useOverlay

Um composable para controlar overlays programaticamente.

Uso

Use o composable useOverlay, importado automaticamente, para controlar programaticamente os componentes Modal e Slideover.

  • The useOverlay composable is created using createSharedComposable, ensuring that the same overlay state is shared across your entire application.
Para retornar um valor do overlay, você pode usar await em overlay.open(). Para que isso funcione, no entanto, o componente de overlay precisa emitir um evento close. Veja o exemplo abaixo para mais detalhes.

API

useOverlay()

O composable useOverlay fornece métodos para gerenciar overlays globalmente. Cada overlay criado retorna uma instância com seus próprios métodos.

create()

create(component: T, options: OverlayOptions): OverlayInstance

Cria um overlay e retorna uma instância de fábrica.

Parâmetros

component
T required
The overlay component to render.
options
OverlayOptions
Configuration options for the overlay.

open()

open(id: symbol, props?: ComponentProps<T>): OpenedOverlay<T>

Open an overlay by its id.

Parâmetros

id
symbol required
The identifier of the overlay.
props
ComponentProps<T>
An optional object of props to pass to the rendered component.

close()

close(id: symbol, value?: any): void

Close an overlay by its id.

Parâmetros

id
symbol required
The identifier of the overlay.
value
any
A value to resolve the overlay promise with.

closeAll()

closeAll(): void

Close all open overlays.

patch()

patch(id: symbol, props: Partial<ComponentProps<T>>): void

Update an overlay by its id.

Parâmetros

id
symbol required
The identifier of the overlay.
props
Partial<ComponentProps<T>> required
An object of props to update on the rendered component.

unmount()

unmount(id: symbol): void

Remove um overlay do DOM pelo seu id.

Parâmetros

id
symbol required
The identifier of the overlay.

isOpen()

isOpen(id: symbol): boolean

Verifica se um overlay está aberto usando seu id.

Parâmetros

id
symbol required
The identifier of the overlay.

overlays

overlays: Overlay[]

Lista em memória de todos os overlays que foram criados.

API da instância

open()

open(props?: ComponentProps<T>): OpenedOverlay<T>

Abre o overlay. Retorna um OpenedOverlay, que é uma Promise resolvida com o valor emitido pelo evento close.

Parâmetros

props
ComponentProps<T>
An optional object of props to pass to the rendered component.
<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.

Parâmetros

value
any
A value to resolve the overlay promise with.

patch()

patch(props: Partial<ComponentProps<T>>): void

Atualiza as props do overlay.

Parâmetros

props
Partial<ComponentProps<T>> required
An object of props to update on the rendered component.
<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>

Exemplos

Com múltiplos overlays

Este exemplo demonstra como gerenciar múltiplos overlays e passar dados entre eles:

<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>
  <NButton label="Open Modal" @click="openModalA" />
</template>

Diálogo de confirmação

Este exemplo demonstra como criar um padrão reutilizável de diálogo de confirmação usando um composable useConfirmDialog personalizado que envolve o useOverlay. Essa abordagem permite diálogos opinativos, adaptados a requisitos de negócio e preferências de design específicos.

  1. Crie um componente ConfirmDialog que emite um valor booleano quando fechado:
components/ConfirmDialog.vue
<script lang="ts" setup>
interface ConfirmDialogProps {
  title?: string
  description?: string
}

defineProps<ConfirmDialogProps>()

const emits = defineEmits<{
  close: [value: boolean]
}>()
</script>

<template>
  <NModal
    :title="title"
    :description="description"
    :dismissible="false"
    :ui="{ footer: 'justify-end' }"
  >
    <template #footer>
      <NButton label="Cancel" color="neutral" variant="outline" @click="emits('close', false)" />
      <NButton label="Confirm" color="neutral" @click="emits('close', true)" />
    </template>
  </NModal>
</template>
  1. Crie um composable useConfirmDialog que retorna uma Promise:
composables/useConfirmDialog.ts
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()
  }
}
  1. Use o composable nos seus componentes:
<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>
  <NButton label="Delete item" @click="handleDelete" />
</template>

Ressalvas

Provide / Inject

Ao abrir overlays programaticamente (ex.: modais, slideovers, etc.), o componente de overlay só consegue acessar valores injetados a partir do componente que contém UApp (normalmente app.vue ou componentes de layout). Isso acontece porque os overlays são montados fora do contexto da página pelo componente UApp.

Por isso, usar provide() em páginas ou componentes pais não é suportado diretamente. Para passar valores fornecidos aos overlays, a abordagem recomendada é usar props:

<script setup lang="ts">
import { LazyModalExample } from '#components'

const overlay = useOverlay()

const providedValue = inject('valueProvidedInPage')

const modal = overlay.create(LazyModalExample, {
  props: {
    providedValue
  }
})
</script>