Dialog
Open focused content above the page with modal or non-modal behavior.
Usage
Modal
Keep focus inside the open dialog and restore it to the trigger when the dialog closes.
Keep focus inside the open dialog and restore it to the trigger when the dialog closes.
<!-- Dialog / Modal -->
<script setup lang="ts">
import { DialogRoot, DialogTrigger, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from '@sectile/vue/dialog'
</script>
<template>
<DialogRoot>
<DialogTrigger>Open deployment</DialogTrigger>
<DialogOverlay class="dialog-overlay" />
<DialogContent>
<DialogTitle>Deployment</DialogTitle>
<DialogDescription>Review the release before continuing.</DialogDescription>
<DialogClose>Close</DialogClose>
</DialogContent>
</DialogRoot>
</template>Non modal
Leave surrounding content interactive while the dialog remains open.
Leave surrounding content interactive while the dialog remains open.
<!-- Dialog / Non Modal -->
<script setup lang="ts">
import { DialogRoot, DialogTrigger, DialogContent, DialogTitle, DialogDescription, DialogClose } from '@sectile/vue/dialog'
</script>
<template>
<DialogRoot :modal="false">
<DialogTrigger>Open deployment details</DialogTrigger>
<DialogContent>
<DialogTitle>Deployment details</DialogTitle>
<DialogDescription>
Keep the page interactive while these details remain open.
</DialogDescription>
<DialogClose>Close</DialogClose>
</DialogContent>
</DialogRoot>
</template>Controlled
Let the parent own the current value and apply accepted changes back to the component.
Let the parent own the current value and apply accepted changes back to the component.
<!-- Dialog / Controlled -->
<script setup lang="ts">
import { DialogRoot, DialogTrigger, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose } from '@sectile/vue/dialog'
import { ref } from 'vue'
const open = ref(false)
</script>
<template>
<DialogRoot v-model:open="open">
<DialogTrigger>Open deployment</DialogTrigger>
<DialogOverlay class="dialog-overlay" />
<DialogContent>
<DialogTitle>Deployment</DialogTitle>
<DialogDescription>Review the release before continuing.</DialogDescription>
<DialogClose>Close</DialogClose>
</DialogContent>
</DialogRoot>
</template>Outside interaction
closeOnInteractOutside controls whether a pointer interaction outside the content closes it. Elements in interactOutsideExclusions stay interactive in a modal and do not count as outside. For conditional decisions, call preventDefault() from the interact-outside event.
<DialogRoot
:interact-outside-exclusions="[ignoredElement]"
@interact-outside="(event) => {
if (event.isInside(temporarilyIgnoredElement)) event.preventDefault()
}"
/>API
Vue package: @sectile/vue/dialog
DialogRootDialogTriggerDialogPortalDialogOverlayDialogContentDialogTitleDialogDescriptionDialogClose
Props
DialogRootProps
alignAlignment of positioned content relative to its anchor.
arrowPaddingMinimum space kept between an arrow and the edge of positioned content.
autoFocusWhether focus moves into the component when it opens.
avoidCollisionsWhether positioned content may flip or shift to remain visible.
closeOnInteractOutsideWhether interaction outside the content closes it.
collisionBoundaryBoundary used to keep positioned content visible.
collisionPaddingSpace kept between positioned content and its collision boundary.
defaultOpenInitial uncontrolled open state.
disabledWhether interaction is unavailable.
hideWhenDetachedWhether positioned content hides when its anchor leaves the layout.
initialFocusElement or resolver that receives focus when the component opens.
interactOutsideExclusionsElements that stay interactive and do not count as outside interaction.
labelAccessible name announced for the control.
modalWhether open content blocks interaction with the surrounding page.
openWhether the associated popup or disclosure is open.
restoreFocusWhether focus returns to the trigger when open content closes.
sidePreferred side of the anchor for positioned content.
sideOffsetDistance between positioned content and its anchor.
strategyCSS positioning strategy used for anchored content.
trackingUpdate strategy used while anchored content is open.
trapFocusWhether keyboard focus stays inside open content.
unmountOnExitWhether presence-managed content is removed from the DOM after its exit motion completes.
DialogPartProps
asElement or component rendered for this part.
asChildWhether to merge this part into its single child instead of rendering a wrapper.
DialogPortalProps
deferWhether Teleport target resolution waits until the end of the current mount or update tick.
disabledWhether interaction is unavailable.
toTeleport target for portalled content.
Slots
DialogRootSlotProps
disabledWhether interaction is unavailable.
openWhether the associated popup or disclosure is open.
Other types
DialogOpenChangeHandler
type DialogOpenChangeHandler = PopupFactoryOptions['onOpenChange']DialogInteractOutsideHandler
type DialogInteractOutsideHandler = NonNullable<PopupFactoryOptions['onInteractOutside']>Parts
Shared scope: [data-scope="dialog"]. Combine it with a part selector to keep styles local to this component.
| Part | Selector | Role | Extra attributes |
|---|---|---|---|
trigger | [data-part="trigger"] | Opens, closes, or activates the associated content. | — |
overlay | [data-part="overlay"] | Covers surrounding content while a modal surface is open. | — |
content | [data-part="content"] | Contains the component content shown for the active state. | — |
title | [data-part="title"] | Labels the associated content. | — |
description | [data-part="description"] | Describes the associated content or decision. | — |
close | [data-part="close"] | Closes or dismisses the current surface. | — |
Keyboard interaction
| Key | Behavior |
|---|---|
| Enter / Space | Activate the trigger or focused action. |
| Tab / Shift+Tab | Move through available controls; modal content keeps focus inside. |
| Escape | Close the popup and restore focus when configured. |
Accessibility
The dialog connects title and description, isolates modal background content, traps focus, locks page scroll, and restores focus on close.
See the corresponding WAI-ARIA pattern for the host accessibility contract.
