Modal
The Modal component provides the base dialog shell used across the site. It handles focus trapping, scroll locking, and cleanup for Astro view transitions, while exposing a small API for external triggers.
Overview
Section titled “Overview”- Type: Utility component
- Category: Overlays
- Complexity: Advanced
- File:
src/components/Modal.astro - Used by:
RegistrationModal,EventHeaderSection
Features
Section titled “Features”- Accessible dialog - Proper ARIA attributes and focus handling
- Focus trap - Keeps Tab navigation inside the modal
- Scroll lock - Prevents background scrolling (with iOS Safari support)
- Close handlers - Overlay click, close button, and Escape key
- Astro-safe cleanup - Removes listeners on
astro:before-swap
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
id | string | ✅ Yes | - | Unique modal identifier used by triggers |
title | string | ✅ Yes | - | Modal heading displayed in the header |
maxWidth | `‘sm' | 'md' | 'lg' | 'xl' |
-
Import the component in the page or layout:
---import Modal from '@/components/Modal.astro';--- -
Render the modal with a unique
idand content:<Modal id="contact-modal" title="Contact FiNAN" maxWidth="xl"><p class="text-gray-700">Hello from the modal body.</p></Modal> -
Wire up a trigger by calling the modal API in client-side script:
<button data-modal-trigger="contact-modal">Open modal</button><script>document.addEventListener('astro:page-load', () => {const trigger = document.querySelector('[data-modal-trigger="contact-modal"]');const modal = document.querySelector('[data-modal="contact-modal"]');if (trigger && modal && typeof modal._openModal === 'function') {trigger.addEventListener('click', () => modal._openModal(trigger));}});</script>
Rendering behavior
Section titled “Rendering behavior”- Adds
role="dialog",aria-modal="true", andaria-hiddenattributes - Applies
hiddenclass to toggle visibility - Sets a focus ring on the close button for keyboard users
Accessibility
Section titled “Accessibility”- Focus returns to the trigger element when the modal closes
- Escape key always closes the modal
- Overlay click closes the modal when the overlay element exists
Styling details
Section titled “Styling details”- Overlay:
bg-gray-900/80for a darkened backdrop - Container:
rounded-lg bg-white shadow-2xl - Header:
border-b border-gray-200with centered heading
Related components
Section titled “Related components”- RegistrationModal - Event registration modal built on this shell
- EventHeaderSection - Triggers the registration modal
Source code
Section titled “Source code”View the complete implementation:
https://github.com/poncardasm/finan-website/blob/main/src/components/Modal.astro