Skip to content

QuesoModal

A modal component with comprehensive accessibility support, focus management, and automatic body scroll locking. It uses Vue's Teleport to render at the document body level and provides automatic ARIA attributes and keyboard navigation.

Basic Usage

vue
<template>
    <button @click="openModal()">Open modal</button>

    <queso-modal ref="myModal">
        <p>This is the modal content.</p>
    </queso-modal>
</template>

<script setup lang="ts">
import { ref } from "vue";

import { QuesoModal } from "@components/QuesoModal";

const myModal = ref<InstanceType<typeof QuesoModal> | null>(null);

const openModal = () => {
    myModal.value?.open();
};

const closeModal = () => {
    myModal.value?.close();
};
</script>

Emits

  • Payload: void
  • Description: Emitted when the modal is opened.
  • Payload: void
  • Description: Emitted when the modal is closed.

Slots

default

  • Props: { isModalOpen: boolean, open: () => void, close: () => void }
  • Description: The main modal content.

beforeContent

  • Props: { isModalOpen: boolean, open: () => void, close: () => void }
  • Description: Content to display before the main modal content.

content (alias for default)

  • Props: { isModalOpen: boolean, open: () => void, close: () => void }
  • Description: The main modal content. This slot is an alias for the default slot - you can use either #content or #default slot.

afterContent

  • Props: { isModalOpen: boolean, open: () => void, close: () => void }
  • Description: Content to display after the main modal content.

overlay

  • Props: { isModalOpen: boolean, open: () => void, close: () => void }
  • Description: Custom overlay component. Defaults to <queso-modal-overlay />.

Exposed Methods

open()

Opens the modal and activates focus trapping.

close()

Closes the modal and deactivates focus trapping.

isModalOpen

Reactive boolean indicating the current open state.

Behavior

  • Teleport to Body: Modal is automatically teleported to the document body
  • Scroll Locking: Automatically prevents body scrolling when modal is open
  • Keyboard Support: Escape key closes the modal
  • Accessibility: Complete ARIA attributes and screen reader support
  • Overlay: Default overlay component with click-to-close functionality

Accessibility

The component automatically handles:

  • aria-expanded attribute for screen readers
  • Focus trapping within the modal when it contains focusable elements
  • Escape key support for closing
  • Proper semantic structure
  • Body scroll locking to prevent background interaction

Focus Management

The modal automatically detects if it contains focusable elements and manages focus accordingly:

  • With focusable elements: Activates focus trap to keep focus within the modal
  • Without focusable elements: No focus trap activation
  • Focusable selectors: Includes links, inputs, buttons, and other interactive elements

CSS

Classes

The component applies the following CSS classes:

  • .queso-modal - Base class
  • .is-modal-open - Applied when modal is open
  • .queso-modal__content - Content container

Custom Properties

  • --queso-modal-opacity - Modal opacity (default: 0, changes to 1 when open)
  • --queso-modal-max-width - Content max width (default: 80%)
  • --queso-modal-max-height - Content max height (default: 80%)
  • --queso-modal-z - Modal z-index (default: 400)