Dialog
A dialog is a modal window that appears in front of app content to provide critical information or ask for a decision. It disables all app functionality when it appears and remains on screen until confirmed, dismissed, or a required action has been taken.
Features
- Accessible by default with proper ARIA attributes
- Focus management and focus trapping
- Keyboard navigation support (Escape to close)
- Click outside to dismiss
- Multiple size options
- Custom content and footer support
- Smooth transitions
Props
Prop | Type | Default | Description |
---|---|---|---|
open | boolean | false | Controls the visibility of the dialog |
size | 'sm' \| 'md' \| 'lg' \| 'full' | 'md' | Sets the size of the dialog |
title | string | '' | The title displayed in the dialog header |
description | string | '' | A description text shown below the title |
closeOnClickOutside | boolean | true | Whether clicking outside the dialog closes it |
closeOnEsc | boolean | true | Whether pressing Escape closes the dialog |
onClose | () => void | () => {} | Callback function called when the dialog should close |
children | () => any | () => '' | Function that returns the content to be displayed in the dialog body |
footer | () => any | () => '' | Function that returns the footer content |
Examples
Basic Dialog
<script>
import Dialog from '$lib/components/Dialog/Dialog.svelte';
import Button from '$lib/components/Button/Button.svelte';
let open = false;
</script>
<Button
label="Open Dialog"
variant="primary"
onclick={() => open = true}
/>
{#snippet dialogContent()}
<p>This is the main content of the dialog.</p>
{/snippet}
<Dialog
{open}
onClose={() => open = false}
title="Basic Dialog"
description="This is a basic dialog with a title and description."
children={dialogContent}
/>
Different Sizes
<script>
import Dialog from '$lib/components/Dialog/Dialog.svelte';
import Button from '$lib/components/Button/Button.svelte';
let open = false;
let size = 'md';
</script>
<div class="flex gap-4">
<Button
label="Small Dialog"
variant="secondary"
onclick={() => { size = 'sm'; open = true; }}
/>
<Button
label="Medium Dialog"
variant="secondary"
onclick={() => { size = 'md'; open = true; }}
/>
<Button
label="Large Dialog"
variant="secondary"
onclick={() => { size = 'lg'; open = true; }}
/>
<Button
label="Full Screen Dialog"
variant="secondary"
onclick={() => { size = 'full'; open = true; }}
/>
</div>
{#snippet dialogContent()}
<p>This dialog can be displayed in different sizes.</p>
{/snippet}
<Dialog
{open}
{size}
onClose={() => open = false}
title="Resizable Dialog"
children={dialogContent}
/>
Custom Footer
<script>
import Dialog from '$lib/components/Dialog/Dialog.svelte';
import Button from '$lib/components/Button/Button.svelte';
let open = false;
</script>
<Button
label="Open Dialog with Footer"
variant="outline"
onclick={() => open = true}
/>
{#snippet dialogContent()}
<p>This dialog has custom footer buttons.</p>
{/snippet}
{#snippet dialogFooter()}
<div class="flex justify-end gap-2">
<Button
label="Cancel"
variant="ghost"
onclick={() => open = false}
/>
<Button
label="Confirm"
variant="primary"
onclick={() => {
// handle confirm
open = false;
}}
/>
</div>
{/snippet}
<Dialog
{open}
onClose={() => open = false}
title="Dialog with Footer"
children={dialogContent}
footer={dialogFooter}
/>
Non-Dismissible Dialog
<script>
import Dialog from '$lib/components/Dialog/Dialog.svelte';
import Button from '$lib/components/Button/Button.svelte';
let open = false;
</script>
<Button
label="Open Non-Dismissible Dialog"
variant="ghost"
onclick={() => open = true}
/>
{#snippet dialogContent()}
<div class="flex flex-col gap-4">
<p>This dialog can only be closed using the close button or programmatically.</p>
<div class="flex justify-end">
<Button
label="Close Dialog"
variant="primary"
onclick={() => open = false}
/>
</div>
</div>
{/snippet}
<Dialog
{open}
closeOnClickOutside={false}
closeOnEsc={false}
onClose={() => open = false}
title="Non-Dismissible Dialog"
children={dialogContent}
/>
Accessibility
The Dialog component follows WAI-ARIA guidelines for modal dialogs:
- Uses
role="dialog"
andaria-modal="true"
- Properly manages focus when opened and closed
- Traps focus within the dialog when open
- Provides proper ARIA labeling with
aria-labelledby
andaria-describedby
- Supports keyboard navigation
- Returns focus to the trigger element when closed
Best Practices
Use Clear Titles: Always provide a clear, descriptive title that indicates the purpose of the dialog.
Keep Content Focused: Dialogs should present focused content and clear actions. Avoid overcrowding with too much information.
Provide Clear Actions: When using action buttons in the footer, make their purpose clear and consider using different visual weights for primary and secondary actions.
Handle Escape Key: Unless there’s a specific reason not to, allow users to close the dialog with the Escape key.
Manage Focus: Ensure that focus is properly managed and that users can navigate through all interactive elements using the keyboard.
Consider Mobile: When designing dialog content, ensure it works well on both desktop and mobile devices.