Modal

Stable v1.0.2

A modal and drawer overlay for dialogs, confirmations, or side panels. Handles scroll locking and focus so accessibility isn't something you bolt on after.

Interactive Component Builder

Configure layout placement, sizing, and security behaviors.

Architecture
Center
Medium (md)
Inside (Pinned)
Metadata
Maximized: false
Capabilities & Security
Component Code
<Modal
  v-model="isOpen"
  v-model:isMaximized="isMaximized"
  title="Interactive Modal"
  description="Adjust parameters in the sidebar to see how this adapts."
  maximizable
>
  <p>Your content goes here...</p>
</Modal>

Non-Blocking Messenger Widget

A real-world implementation demonstrating how to disable the backdrop and scroll-blocking to create a floating widget, powered by the BubbleChat component.

Integration Map
<Modal
  v-model="showChatModal"
  v-model:isMinimized="isChatMinimized"
  position="bottom-right"
  size="xs"
  :hideBackdrop="true"
  :blockScroll="false"
  contentClass="sm:mb-4 sm:mr-4 shadow-xl"
>
  <template #header>
    <div
      class="flex items-center gap-2 w-full min-w-0 py-1 px-3 bg-surface/30 rounded-t-md transition-all duration-200"
      :class="isChatMinimized ? 'cursor-pointer hover:bg-surface/50' : 'border-b border-main/50'"
      @click="isChatMinimized ? isChatMinimized = false : null"
    >
      <div class="relative shrink-0 transition-all duration-200" :class="isChatMinimized ? 'w-6 h-6' : 'w-10 h-10'">
        <Image src="https://avatars.githubusercontent.com/u/54705651?v=4" shape="circle" class="w-full h-full border border-main/20 shadow-sm" />
        <span class="absolute bottom-0 right-0 bg-success rounded-full transition-all" :class="isChatMinimized ? 'w-2 h-2 border' : 'w-3 h-3 border-2 border-content'"></span>
      </div>

      <div class="flex flex-col min-w-0 transition-all duration-200" :class="isChatMinimized && 'mt-0.5'">
        <h3 class="font-bold text-main truncate text-sm sm:text-base">Simon Pangan</h3>
        <p v-show="!isChatMinimized" class="text-xs text-muted truncate">Active now</p>
      </div>

      <div class="flex items-center gap-0.5 ml-auto text-primary shrink-0">
        <Button :icon="isChatMinimized ? 'lucide:chevron-up' : 'lucide:minus'" variant="text" size="xs" @click.stop="isChatMinimized = !isChatMinimized" />
        <Button icon="lucide:x" variant="text" size="xs" @click.stop="showChatModal = false" />
      </div>
    </div>
  </template>

  <div class="flex flex-col gap-2 h-[400px] overflow-y-auto overflow-x-hidden">
    <BubbleChat
      v-for="msg in messages"
      :key="msg.id"
      :content="msg.text"
      @longpress="msg.showMenu = true"
    >
      <template #actions>
        <!-- Only the 3-dot button opens the menu, not the whole bubble -->
        <Popover v-model="msg.showMenu">
          <template #trigger>
            <Button icon="lucide:more-vertical" variant="text" size="xs" />
          </template>
          <div class="flex flex-col gap-1 p-1">
            <Button label="Copy" variant="text" />
            <Button label="Delete" variant="text" severity="danger" />
          </div>
        </Popover>
      </template>
    </BubbleChat>
  </div>

  <template #footer>
    </template>
</Modal>

Events & Lifecycle

Bind to lifecycle events to trigger functions during state transitions.

Event Listener Log

Waiting for events...
Template
<Modal
  v-model="isOpen"
  title="Event Tracker"
  maximizable
  minimizable
  @open="logEvent('open')"
  @close="logEvent('close')"
  @minimize="(val) => logEvent('minimize', val)"
  @maximize="(val) => logEvent('maximize', val)"
>
  <p>Events emit boolean payloads indicating their active state changes.</p>
</Modal>

API Reference

Props

Name
Type / Signature
Default
Description
v-model
boolean
false
Controls the visibility of the modal.
v-model:isMaximized
boolean
false
Controls the maximized (full-screen) state.
v-model:isMinimized
boolean
false
Controls the minimized (widget) state.
title
string
""
Text for the built-in modal header.
description
string
""
Secondary text displayed below the title.
size
"auto" | "xs" | "sm" | "md" | "lg" | "xl" | "full"
"md"
Max-width constraint of the modal card.
position
string
"center"
Anchoring layout (e.g., center, right, bottom-left).
scrollBehavior
"inside" | "outside"
"inside"
Inside locks the modal height and scrolls content; Outside scrolls the whole page.
hideBackdrop
boolean
false
Removes the dark overlay backdrop (useful for non-blocking widgets).
blockScroll
boolean
true
Prevents the body from scrolling when modal is open.
dismissableMask
boolean
true
Allows closing the modal by clicking the backdrop.
closeOnEscape
boolean
true
Allows closing the modal using the Escape key.
showCloseIcon
boolean
true
Shows the "x" close icon in the built-in header/toolbar.
maximizable
boolean
false
Shows the maximize icon in the header.
minimizable
boolean
false
Shows the minimize icon in the header.
zIndex
number | string
9999
Stacking order of the modal and its backdrop (backdrop renders at zIndex - 1).
contentClass
string | object
""
Custom CSS classes applied to the modal card container.
overlayClass
string | object
""
Custom CSS classes applied to the full-screen wrapper.

Events

Event Name
Payload Signature
Description
@open
()
Fires when the modal transition starts opening.
@close
()
Fires when the modal closes.
@maximize
(value: boolean)
Fires when the maximize state changes.
@minimize
(value: boolean)
Fires when the minimize state changes.

Slots

Slot Name
Exposed Bindings
Description
default
-
The main body content of the modal.
header
{ is-minimized: boolean }
Overrides the entire built-in header/toolbar area.
title
{ is-minimized: boolean }
Replaces just the title text inside the default header.
footer
{ is-minimized: boolean }
Content pinned to the bottom of the modal.