@archpublicwebsite/modal
v3.0.1
Published
Universal modal system for archipelago hotels
Readme
@archpublicwebsite/modal
Modal shell and animation framework for Archipelago hotel templates.
Overview
@archpublicwebsite/modal provides the low-level modal shell that other modal content
renders inside: a teleported dialog, backdrop, focus trap, ESC/backdrop/swipe-to-close, a
FLIP-based open animation, and theming. It ships one ready-to-use content type,
ModalNotification; everything else (Gallery, Offers, Splash, Form dialogs, and preview
modals) lives in @archpublicwebsite/components,
which depends on this package for the shell.
Features
BaseModalshell: center, fullscreen, and bottom-sheet positionsModalNotification: success, error, warning, and info states- Desktop-first animation: richer FLIP/transform on desktop, a plain fade on mobile, aware of
prefers-reduced-motion - Swipe-to-close on mobile (bottom-sheet), gesture starts from a dedicated handle so it doesn't fire while scrolling modal content
- Dark mode support
- Theming via a single
themeprop (primary/secondary/background color, border radius, color scheme) - Optional SEO metadata (title/description/OG/Twitter tags) applied while a modal is open
- Full TypeScript support
Installation
pnpm add @archpublicwebsite/modal vuevue is a peer dependency. If you use the AOS-aware desktop animation and want the
reduced-motion-respecting enter/leave to look its best, also install AOS's stylesheet — the
shell's own FLIP/transform animation works without it:
pnpm add aosQuick start
<script setup lang="ts">
import { ref } from 'vue'
import { BaseModal, ModalNotification } from '@archpublicwebsite/modal'
import '@archpublicwebsite/modal/style.css'
const isOpen = ref(false)
const content = {
type: 'success' as const,
title: 'Booking confirmed',
message: 'Check your email for details.',
}
</script>
<template>
<button type="button" @click="isOpen = true">
Open
</button>
<BaseModal v-model="isOpen">
<ModalNotification :content="content" />
</BaseModal>
</template>For Gallery, Offers, Splash, Form, or the Google Maps/iframe/PDF/Video previews, import the
matching component from @archpublicwebsite/components instead — see that package's README.
Public API
The package root exports:
BaseModal,ModalNotification- Composables:
useSEO,useAOSResponsive, and others - Modal types
- Modal utilities
BaseModal key attributes
| Prop | Type | Default | Notes |
| --- | --- | --- | --- |
| modelValue | boolean | required | Controls open/close (v-model). |
| position | 'center' \| 'fullscreen' \| 'bottom-sheet' | 'center' | Layout mode. |
| animationLoad / animationClose | ModalTransitionAnimation | 'fade-in-out' | Desktop uses richer animation; mobile resolves to fade. |
| duration | number | 320 | Transition duration in ms. |
| showCloseButton | boolean | true | Renders close button in shell. |
| closeOnEsc | boolean | true | ESC to close. |
| closeOnBackdropClick | boolean | true | Backdrop click to close. |
| showBackdrop | boolean | true | Toggle backdrop layer. |
| enableSwipeClose | boolean | true | Mobile bottom-sheet swipe close. |
| enableFlipAnimation | boolean | true | Enables origin-aware FLIP animation. |
| originElement / originRect | HTMLElement \| null / rect | - | Optional source for FLIP origin. |
| flipTargetSelector | string | 'img' | Selector used to find FLIP target in modal content. |
| theme | ModalThemeConfig | - | Color/spacing/typography overrides. |
| accessibility | A11yAttributes | { ariaLabel: 'Modal' } | Accessibility metadata. |
| seoTitle / seoDescription | string | - | Applied while modal is open. |
| analyticsEvent | string | - | Emits analytics event name on open. |
Events
| Event | Payload | Description |
| --- | --- | --- |
| update:modelValue | boolean | Two-way open state. |
| open | - | Fired after open transition begins. |
| close | - | Fired when modal requests close. |
| confirm | data?: any | Optional confirm action payload. |
| analytics | eventName: string | Fired when analyticsEvent is provided. |
AI-agent implementation checklist
- Always bind
v-modeland source of truth from parent state. - Pick
positionintentionally:centerfor dialogs,bottom-sheetfor mobile-heavy quick actions,fullscreenfor immersive flows. - Keep
closeOnEscandcloseOnBackdropClickenabled unless business-critical blocking is required. - If using FLIP, pass a stable
originElementfrom the clicked card/thumbnail. - Provide
accessibility.ariaLabelfor every modal instance. - Apply
seoTitle/seoDescriptiononly when modal content is index-worthy and unique.
Contributing
See the root README for contribution guidelines.
License
MIT
