Bridge UI

Modal

Modal overlay with portal, backdrop, and focus management.

Introduction

Modal is a lower-level overlay primitive. It renders children in front of a backdrop, locks page scroll by default, and manages focus while open.

Modal vs dialog

Use Modal when you need a custom content shell (often with Card). Prefer useDialogAction for confirm/cancel flows with a standard footer.

Modal vs blocking dialog behavior: Modal itself is a generic overlay—it does not require user input to dismiss unless you configure it that way. For blocking dialogs that demand an explicit decision (confirm delete, accept terms), combine Modal with Card for structured title and actions, and set persistent so Escape and backdrop clicks do not close the overlay until the user chooses a footer action. For non-blocking overlays or drawers, leave persistent false so users can dismiss quickly.

Unlike Snackbar, Modal interrupts interaction with the page below through backdrop and focus trapping.

Import

import { Modal } from "@bridge-ui/vue/Components/Modal";
import { Modal } from "@bridge-ui/react/Components/Modal";

Basic usage

Pair a trigger such as a Button with a controlled Modal. Place content such as a Card inside the dialog panel.

Sizes

Use the size prop on Modal to set max width from the sm breakpoint up. Available sizes: sm, md (default), lg, xl, and full.

Persistent

When persistent is true, Escape and backdrop clicks do not close the modal. Provide an explicit close action inside the content.

Card composition

Combine Modal with Card for structured dialogs. Use Card slots for title, body, and footer actions. Additional Modal props such as blur, size, and transition customize the overlay experience.

Align

Use the align prop to position the panel on all breakpoints. Available values include middle-center (default), top-start, bottom-end, and others.

Breaking change

align now applies on every viewport. Mobile no longer forces a bottom sheet. Use useBreakpoint to restore bottom-sheet-on-mobile behavior.

Responsive align

Combine Modal with useBreakpoint when you want a different align per viewport—for example a bottom sheet on mobile and a centered dialog on larger screens.

Transitions and blur

Set transition to control enter/leave animation (fade, scale, slide-up, slide-down, or none). Combine with blur on the backdrop for depth.

Nested modals

Place a second Modal inside the first. Each layer gets its own overlay and a higher z-index. Escape closes only the topmost modal.

Scroll lock

While open, Modal locks body scroll and adds padding-right on document.body so page content does not shift when the scrollbar disappears. Fixed or sticky UI outside the document flow is not covered by that padding. Bridge UI sets --bridge-scrollbar-compensation on :root with the scrollbar width for the duration of the lock (and clears it when the last locking layer closes):

.my-fixed-header {
  padding-inline-end: var(--bridge-scrollbar-compensation, 0px);
}

Set disableScrollLock if the page should keep scrolling behind the overlay.

Card, Button, Drawer, useBreakpoint

Accessibility

  • Content under an active modal is inert—users cannot interact with the page behind the overlay.
  • Focus is trapped inside the modal by default (disableEnforceFocus disables this).
  • Focus returns to the trigger on close unless disableRestoreFocus is set.
  • Escape closes the modal when closeOnEscape is true and persistent is false.
  • When using Card inside Modal, ensure the card title is referenced for context. Pass aria-labelledby and aria-describedby on Modal via root attributes or customProps pointing to title and description element IDs.
  • Enable autoFocus to move focus to the first focusable element when the modal opens.

Anatomy

<div> <!-- Modal root (portaled) -->
  <div> <!-- overlay / backdrop -->
  <div> <!-- paper panel -->
    <!-- children: Card, form, or custom content -->
  </div>
</div>

Target overlay and panel styling with the classes prop. align applies on all breakpoints; size still sets max width from the sm breakpoint up.

API

Prop Type Default Description
v-model boolean Two-way binding for overlay visibility.
@close Fired when the user dismisses (Escape or click-away). Not fired when the parent sets v-model={false} directly.
@show-change (show: boolean) => void Equivalent to onShowChange when you prefer events over a callback prop.
Prop Type Default Description
show boolean Whether the overlay is visible. Use with onShowChange for controlled state.
onShowChange (show: boolean) => void Called when visibility changes.
onClose () => void Fired when the user dismisses (Escape or click-away). Not fired when the parent sets show={false} directly.
Prop Type Default Description
size ModalSize "md" Max width from the sm breakpoint up.
align ModalAlign "middle-center" Panel position on all breakpoints. Use useBreakpoint for per-viewport align.
transition ModalTransition "fade" Enter/leave animation for overlay and panel.
blur ModalBlur "none" Backdrop blur on the overlay.
persistent boolean false When true, Escape and overlay clicks do not close the modal.
closeOnEscape boolean true Whether the modal closes on Escape.
closeOnOverlay boolean true Whether the modal closes on overlay click.
hideBackdrop boolean false When true, the backdrop overlay is not rendered.
scroll ModalScroll "body" Where scroll happens: page (body) or panel (paper).
autoFocus boolean false Focus the first focusable element on open.
disableEnforceFocus boolean false When true, focus is not trapped inside the modal.
disableRestoreFocus boolean false When true, focus is not restored on close.
disableScrollLock boolean false When true, body scroll is not locked while open.
keepMounted boolean false When true, the modal stays mounted after closing (hidden).
teleportTo string | false "body" Portal target. Pass false to render in place.
classes ModalClasses Class overrides for modal parts.
customProps ModalCustomProps Props forwarded to each modal part.