Developer Docs
Quick reference guides with props tables, usage examples, and best practices for rapid development
Modal
Flexible modal dialog with glass morphism and keyboard support
Modal
A flexible modal dialog with glass morphism effects, smooth animations, and keyboard navigation. Perfect for forms, confirmations, and displaying detailed content without leaving the current page.
🔧 Props
Modal component configuration options.
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | 'modal' | Unique identifier for the modal |
| title | string | undefined | Modal title (optional, for aria-labelledby) |
| closeFunction | Function | undefined | Function to call when modal should close |
| closeOnBackdrop | boolean | true | Whether clicking backdrop closes modal |
| class | string | 'max-w-lg' | CSS classes for modal card (auto-adds max-w-lg if no max-w-* provided) |
| containerClass | string | '' | CSS classes for backdrop container |
💻 Basic Usage
Simple modal with default size (max-w-lg) and behavior.
const showModal = van.state(false);
// Render button
Button({
onclick: () => showModal.val = true
}, 'Open Modal')
// Render modal conditionally
() => showModal.val ? Modal({
closeFunction: () => showModal.val = false
},
div({ class: 'p-6' },
h2({ class: 'text-xl font-semibold mb-4' }, 'Modal Title'),
p({ class: 'text-smoke mb-4 ' + tClose }, 'Modal content goes here.'),
Button({
onclick: () => showModal.val = false
}, 'Close')
)
) : ''📐 Size Variants
Control modal width using Tailwind max-w-* utilities.
(max-w-sm)
(max-w-md)
(max-w-lg - default)
(max-w-xl)
(max-w-2xl)
// Small modal
Modal({
class: 'max-w-sm',
closeFunction: closeHandler
}, content)
// Medium modal
Modal({
class: 'max-w-md',
closeFunction: closeHandler
}, content)
// Default (large) - auto-applied
Modal({ closeFunction: closeHandler }, content) // Gets max-w-lg
// Extra large modal
Modal({
class: 'max-w-2xl',
closeFunction: closeHandler
}, content)
// Full width (with explicit max)
Modal({
class: 'w-[90vw] max-w-4xl',
closeFunction: closeHandler
}, content)📑 Form Modal
Modal containing a form with validation and submit handling.
const showFormModal = van.state(false);
const userName = van.state('');
const userEmail = van.state('');
// Form modal
() => showFormModal.val ? Modal({
title: 'Edit Profile',
closeFunction: () => showFormModal.val = false,
class: 'max-w-md'
},
div({ class: 'p-6' },
h3({ class: 'text-lg font-semibold mb-4' }, 'Edit Profile'),
form({
class: 'space-y-4',
onsubmit: (e) => {
e.preventDefault();
// Handle submit
showFormModal.val = false;
}
},
Input({
label: 'Name',
value: userName,
placeholder: 'Enter your name',
oninput: e => userName.val = e.target.value
}),
Input({
label: 'Email',
value: userEmail,
type: 'email',
placeholder: 'Enter your email',
oninput: e => userEmail.val = e.target.value
}),
div({ class: 'flex gap-3 pt-2' },
Button({ type: 'submit', class: 'vwfcolor-sky' }, 'Save'),
Button({
type: 'button',
class: 'outerline',
onclick: () => showFormModal.val = false
}, 'Cancel')
)
)
)
) : ''🔒 Disable Backdrop Close
Prevent closing modal by clicking outside (useful for forms with unsaved changes).
Modal({
closeFunction: () => showModal.val = false,
closeOnBackdrop: false // Disable backdrop close
},
div({ class: 'p-6' },
h2('Important Action'),
p('Click button or press Escape to close'),
Button({
onclick: () => showModal.val = false
}, 'Confirm')
)
)🧭 Keyboard Navigation
Modal supports keyboard navigation for accessibility.
- ✓Escape key - Always closes the modal (unless closeFunction not provided)
- ✓Tab key - Cycles through focusable elements inside modal
- ✓Backdrop is focusable (tabindex="-1") for keyboard event handling
- ✓Prevents event propagation for Escape key
// Keyboard behavior is automatic
Modal({
closeFunction: () => showModal.val = false
}, content)
// Escape key triggers closeFunction
// No configuration needed⚡️ Best Practices
✓ Do This
✓Always Provide Close Function
- Include closeFunction prop to ensure users can dismiss the modal
✓Use Appropriate Sizing
- Choose max-w-* classes that fit your content (sm for simple forms, 2xl for detailed views)
✓Add Proper Padding
- Use p-6 for modal content to ensure comfortable spacing and readability
✓Include Visible Close Button
- Add an explicit close button for mobile users who may not know about backdrop/Escape key
✓Disable Backdrop Close for Forms
- Use closeOnBackdrop: false for forms with unsaved changes to prevent accidental loss
✓Use ARIA Labels
- Provide title prop for proper aria-labelledby and screen reader support
✓Keep Content Focused
- Keep modal content concise and focused on a single task or purpose
✗ Avoid This
✗Don't Nest Modals
- Avoid modal-within-modal patterns; use sequential modals or different UI patterns instead
✗Don't Make Modals Full-Screen
- Avoid full-screen modals on desktop; use a dedicated page instead
✗Don't Forget Form Submission
- Always handle form onsubmit events properly in modal forms
✗Don't Misuse for Simple Confirmations
- Use ConfirmModal component for simple yes/no confirmations instead of full Modal
✗Don't Overload with Content
- Avoid putting too much content; rely on scrolling for longer content
✗Don't Disable Keyboard Navigation
- Never prevent Escape key or Tab navigation; users expect these to work
✨ Key Features
⭑Glass Morphism Backdrop
- Beautiful glass effect with bg-black/50 and backdrop-blur for modern aesthetics
⭑Smooth Animations
- Fade-in backdrop and zoom-in modal animations for polished transitions
⭑Smart Default Sizing
- Automatic max-w-lg sizing when no max-w-* class is provided
⭑Keyboard Navigation
- Escape key closes modal, Tab key cycles through focusable elements
⭑Configurable Backdrop Close
- Optional closeOnBackdrop prop to control whether clicking outside dismisses modal
⭑Responsive Positioning
- Centered positioning with bottom-10 offset for comfortable mobile viewing
⭑Auto-Scroll for Tall Content
- Max height of 90vh with automatic scrolling for content overflow
⭑Click Propagation Prevention
- Clicks inside modal are contained to prevent unwanted backdrop dismissal
⭑ARIA Accessibility
- Built-in ARIA support with role, aria-modal, and aria-labelledby attributes
⭑Complete Customization
- FilterClassName support for full control over modal and container styling
💡 Common Use Cases
Typical scenarios where Modal component provides the best user experience.
📝Forms & Data Entry
Edit profile, create post, add item - any form that needs focus.
Modal({
title: 'Create Post',
class: 'max-w-lg',
closeFunction: closeHandler
},
div({ class: 'p-6' },
form(/* form content */)
)
)🖼️Image/Media Viewer
Display full-size images, videos, or galleries.
Modal({
class: 'max-w-4xl',
closeFunction: () => showImage.val = false
},
img({ src: imageUrl, class: 'w-full' })
)📄Detailed Information
Show full product details, user profiles, or documentation.
Modal({
title: 'Product Details',
class: 'max-w-2xl',
closeFunction: closeHandler
},
div({ class: 'p-6' },
// Detailed content with sections
)
)🔐Authentication
Login, signup, or password reset flows.
Modal({
title: 'Sign In',
class: 'max-w-md',
closeOnBackdrop: false,
closeFunction: closeHandler
},
div({ class: 'p-6' },
form(/* auth form */)
)
)Explore More Components
Browse other component categories