Modal
The Modal component provides a flexible dialog system for displaying content that requires user attention or input. It includes comprehensive accessibility features, focus management, and customizable behaviors.
Modal Sizes
Different modal sizes for various content needs
Code
<Modal size="sm">Small modal content</Modal>
<Modal size="md">Medium modal content</Modal>
<Modal size="lg">Large modal content</Modal>
<Modal size="full">Full modal content</Modal> Size specifications
Available size options and their dimensions
Small (sm)
max-width: 400px Quick confirmationsMedium (md)
max-width: 560px Standard contentLarge (lg)
max-width: 800px Complex formsFull
max-width: calc(100vw - 32px) Immersive experiencesAPI Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | false | Controls modal visibility |
onClose | () => void | - | Callback when modal should close |
size | 'sm' \| 'md' \| 'lg' \| 'full' | 'md' | Modal size variant |
closeOnBackdrop | boolean | true | Close modal when clicking backdrop |
closeOnEscape | boolean | true | Close modal when pressing Escape |
showClose | boolean | true | Show close button in top-right corner |
class | string | '' | Additional CSS classes |
Sizes
- Small (
sm): 400px max-width, 16px padding - Ideal for confirmations - Medium (
md): 560px max-width, 24px padding - Default for most content - Large (
lg): 800px max-width, 32px padding - Rich content and forms - Full: Nearly full viewport, 40px padding - Complex workflows
Usage Examples
Basic Modal
<script>
import Modal from '$lib/shared/components/overlays/Modal.svelte';
let isOpen = false;
</script>
<Modal bind:open={isOpen} onClose={() => isOpen = false}>
<h2>Modal Title</h2>
<p>Modal content goes here.</p>
</Modal> Form Modal
<Modal bind:open={formOpen} size="md" onClose={() => formOpen = false}>
<h2>Edit Profile</h2>
<form onsubmit|preventDefault={handleSubmit}>
<div class="form-field">
<label>Name</label>
<input type="text" bind:value={name} />
</div>
<div class="modal-actions">
<button type="submit">Save</button>
<button type="button" onclick={() => formOpen = false}>Cancel</button>
</div>
</form>
</Modal> Confirmation Dialog
<Modal
bind:open={confirmOpen}
size="sm"
closeOnBackdrop={false}
onClose={() => confirmOpen = false}
>
<h2>Confirm Deletion</h2>
<p>Are you sure you want to delete this item? This action cannot be undone.</p>
<div class="modal-actions">
<button onclick={handleDelete}>Delete</button>
<button onclick={() => confirmOpen = false}>Cancel</button>
</div>
</Modal> Disable Close Methods
<!-- No backdrop close -->
<Modal
bind:open={modal1}
closeOnBackdrop={false}
onClose={() => modal1 = false}
>
Content here
</Modal>
<!-- No escape key close -->
<Modal
bind:open={modal2}
closeOnEscape={false}
onClose={() => modal2 = false}
>
Content here
</Modal>
<!-- No close button -->
<Modal
bind:open={modal3}
showClose={false}
onClose={() => modal3 = false}
>
Content here
</Modal> Accessibility Features
Focus Management
- Focus is trapped within the modal when open
- Focus returns to the trigger element when closed
- Tab cycles through focusable elements inside modal
Keyboard Navigation
- Escape: Closes modal (if
closeOnEscapeis true) - Tab: Moves focus to next focusable element
- Shift + Tab: Moves focus to previous focusable element
Screen Reader Support
- Modal uses
role="dialog"andaria-modal="true" - Proper ARIA labeling with
aria-labelledbyandaria-describedby - Background content is hidden from assistive technology
Body Scroll Lock
- Body scrolling is disabled when modal is open
- Scroll position is preserved when modal closes
- Mobile touch scrolling is properly handled
Design Tokens
The Modal component uses the following design tokens:
- Typography:
--typography-heading-*,--typography-body-* - Spacing:
--space-4,--space-6,--space-8,--space-10 - Colors:
--background,--border,--foreground - Shadows:
--shadow-2xl - Radius:
--radius-lg - Transitions:
--transition-base
Best Practices
Content Guidelines
- Keep modal content focused and actionable
- Use clear, descriptive titles
- Provide obvious ways to close or cancel
- Avoid nested modals when possible
Size Selection
- Use small modals for simple confirmations
- Medium modals work for most forms and content
- Large modals for complex forms or rich media
- Full modals for multi-step workflows
Interaction Design
- Always provide a way to close the modal
- Use loading states for async operations
- Validate forms before submission
- Confirm destructive actions
Technical Notes
Performance
- Modal content is only rendered when
openis true - Focus trap and scroll lock are cleaned up automatically
- Smooth animations with hardware acceleration
Browser Support
- Full support for all modern browsers
- Graceful degradation for older browsers
- Mobile-optimized touch interactions
Framework Integration
- Works with SvelteKit SSR
- Compatible with Svelte 5 runes
- TypeScript support included