Overlay
Modal
A modal overlay for confirmations, forms, alerts, and custom content with support for scrollable, fullscreen, and non-dismissible modes.
Playground
Experiment with different props in real-time.
Basic Usage
Import and use the Modal component with bind:open, a title, and description.
<script lang="ts">
import { Modal, Button } from 'sv5ui';
let open = $state(false);
</script>
<Button label="Open Modal" onclick={() => (open = true)} />
<Modal
bind:open
title="Basic Modal"
description="This is a simple modal with a title and description."
>
{#snippet body()}
<p>This is the body content of the modal.</p>
{/snippet}
</Modal>With Footer
Add action buttons using the footer snippet.
<script lang="ts">
import { Modal, Button } from 'sv5ui';
let open = $state(false);
</script>
<Button label="Open Modal" onclick={() => (open = true)} />
<Modal
bind:open
title="Confirm Action"
description="Are you sure you want to proceed?"
>
{#snippet body()}
<p>This action cannot be undone. Please confirm to continue.</p>
{/snippet}
{#snippet footer()}
<Button variant="outline" color="surface" label="Cancel" onclick={() => (open = false)} />
<Button label="Confirm" onclick={() => (open = false)} />
{/snippet}
</Modal>Scrollable
Enable the scrollable prop for modals with long content.
<script lang="ts">
import { Modal, Button } from 'sv5ui';
let open = $state(false);
</script>
<Button label="Open Scrollable" onclick={() => (open = true)} />
<Modal
bind:open
title="Terms of Service"
scrollable
>
{#snippet body()}
<div class="space-y-4">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
<!-- Long scrollable content -->
</div>
{/snippet}
</Modal>Fullscreen
Use the fullscreen prop to make the modal fill the entire viewport.
<script lang="ts">
import { Modal, Button } from 'sv5ui';
let open = $state(false);
</script>
<Button label="Open Fullscreen" onclick={() => (open = true)} />
<Modal
bind:open
title="Fullscreen Modal"
fullscreen
>
{#snippet body()}
<p>This modal fills the entire viewport.</p>
{/snippet}
</Modal>Custom Header
Use the header snippet to fully customize the header layout.
<script lang="ts">
import { Modal, Button } from 'sv5ui';
let open = $state(false);
</script>
<Button label="Open Custom Header" onclick={() => (open = true)} />
<Modal bind:open>
{#snippet header()}
<div class="flex items-center gap-3">
<div class="flex h-10 w-10 items-center justify-center rounded-full bg-primary/10">
<span class="text-primary text-lg">!</span>
</div>
<div>
<h3 class="text-lg font-semibold">Custom Header</h3>
<p class="text-sm text-on-surface/60">With a custom icon layout</p>
</div>
</div>
{/snippet}
{#snippet body()}
<p>The header snippet lets you fully customize the header area.</p>
{/snippet}
</Modal>Non-dismissible
Set dismissible={false} to prevent closing by clicking outside or pressing Escape.
<script lang="ts">
import { Modal, Button } from 'sv5ui';
let open = $state(false);
</script>
<Button label="Open Non-dismissible" onclick={() => (open = true)} />
<Modal
bind:open
title="Important Notice"
dismissible={false}
>
{#snippet body()}
<p>This modal cannot be closed by clicking outside or pressing Escape. You must use the button below.</p>
{/snippet}
{#snippet footer()}
<Button label="I Understand" onclick={() => (open = false)} />
{/snippet}
</Modal>UI Slots
Use the ui prop to override classes on specific internal elements of the Modal.
| Slot | Description |
|---|---|
overlay | Backdrop behind the modal — controls background color and opacity |
content | Main modal container — controls width, padding, border radius, shadow |
header | Top section containing title and description — controls layout and spacing |
wrapper | Wraps the title and description text — controls text layout |
title | Modal title text — controls font size, weight, color |
description | Modal description text — controls font size and opacity |
body | Main content area — controls padding and overflow behavior |
footer | Bottom section for actions — controls layout, gap, and alignment |
close | Close button in the header — controls position, size, and icon |
Snippets
Use Svelte 5 snippets to customize specific parts of the Modal.
| Snippet | Type | Description |
|---|---|---|
children | Snippet | Trigger element — clicking opens the modal |
content | Snippet | Custom content replacing the entire default layout |
header | Snippet | Custom header section |
titleSlot | Snippet | Custom title content — overrides title prop |
descriptionSlot | Snippet | Custom description content — overrides description prop |
body | Snippet | Main body content area |
footer | Snippet | Footer area for action buttons |
closeSlot | Snippet | Custom close button — replaces default close icon |
Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | false | |
onOpenChange | (open: boolean) => void | - | |
title | string | - | |
description | string | - | |
overlay | boolean | true | |
scrollable | boolean | false | |
transition | boolean | true | |
fullscreen | boolean | false | |
close | boolean | ModalCloseProps | true | |
dismissible | boolean | true | |
trapFocus | boolean | true | |
preventScroll | boolean | true | |
portal | boolean | true | |
class | string | - | |
ui | Record<Slot, Class> | - |