Modal component
The kit:modal component displays an overlay panel above the main content. It is designed for dialogs, contextual messages, forms or alerts requiring direct interaction.
The modal can be centered, fixed at the top or bottom of the screen, and closes in different ways depending on the options activated (outside click, Escape key, etc.). It is a flexible alternative to kit:dialog when you need more control over the structure, behavior or styling of the modal content, or when you want to manage the backdrop at the application level.
<script lang="ts">
let open = $state(false);
</script>
<kit:btn onclick={() => (open = true)}>Open modal</kit:btn>
<kit:modal bind:open>
<h3 style="margin: 0 0 0.5rem;">Confirm action</h3>
<p style="margin: 0 0 1.25rem; opacity: 0.7;">
Are you sure you want to continue? This action cannot be undone.
</p>
<div style="display: flex; justify-content: flex-end; gap: 0.5rem;">
<kit:btn variant="text" onclick={() => (open = false)}>Cancel</kit:btn>
<kit:btn onclick={() => (open = false)}>Confirm</kit:btn>
</div>
</kit:modal>
kit:modal is a div-based overlay positioned fixed over the viewport. Unlike kit:dialog, it does not use the native <dialog> element and has no built-in backdrop a global backdrop is typically managed at the application level. Use contain to embed the modal relative to its parent instead.
open is bindable set it to true to open, false to close, or bind it to react to closes.
Examples of modal
position
Controls the vertical alignment of the content panel.
- position:
'top' | 'center' | 'bottom'='center'
<script lang="ts">
type ModalPosition = 'top' | 'center' | 'bottom';
let position = $state<ModalPosition>('center');
let open = $state(false);
function show(pos: ModalPosition) {
position = pos;
open = true;
}
</script>
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
<kit:btn onclick={() => show('top')}>Top</kit:btn>
<kit:btn onclick={() => show('center')}>Center</kit:btn>
<kit:btn onclick={() => show('bottom')}>Bottom</kit:btn>
</div>
<kit:modal bind:open {position}>
<p style="margin: 0 0 1rem; opacity: 0.7;">Position: <strong>{position}</strong></p>
<kit:btn onclick={() => (open = false)}>Close</kit:btn>
</kit:modal>
size
Controls the max-width of the content panel. 'full' renders as a bottom sheet spanning the full viewport width.
- size:
'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full'='md'
<script lang="ts">
type ModalSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
const sizes: ModalSize[] = ['xs', 'sm', 'md', 'lg', 'xl', 'full'];
let size = $state<ModalSize>('md');
let open = $state(false);
function show(s: ModalSize) {
size = s;
open = true;
}
</script>
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
{#each sizes as s (s)}
<kit:btn onclick={() => show(s)}>{s}</kit:btn>
{/each}
</div>
<kit:modal bind:open {size}>
<p style="margin: 0 0 1rem; opacity: 0.7;">Size: <strong>{size}</strong></p>
<kit:btn onclick={() => (open = false)}>Close</kit:btn>
</kit:modal>
persistent
When persistent is set, pressing Escape does not close the modal. The user must interact with the content to dismiss it.
- persitent:
boolean=false
<script lang="ts">
let open = $state(false);
</script>
<kit:btn onclick={() => (open = true)}>Open persistent modal</kit:btn>
<kit:modal bind:open persistent>
<h3 style="margin: 0 0 0.5rem;">Persistent modal</h3>
<p style="margin: 0 0 1.25rem; opacity: 0.7;">
Pressing Escape will not close this modal. You must use the button.
</p>
<kit:btn onclick={() => (open = false)}>Dismiss</kit:btn>
</kit:modal>
Without preprocess Lapikit
If you aren’t using the Lapikit preprocessor in svelte.config.js, import the components directly:
import { Modal } from 'lapikit/components';API Reference
kit:modal
| props | type | description | default |
|---|---|---|---|
| ref $bindable | HTMLElement | Bindable reference to the rendered DOM element. | null |
| s-class | enum'string''array''object' | Sets className on modal. | |
| s-style | enum'string''array''object' | Sets styles on modal. | |
| open $bindable | boolean | Controls visibility. | false |
| persistent | boolean | Prevents closing on Escape. | false |
| contain | boolean | Positions relative to parent instead of viewport. | false |
| closeWithEsc | boolean | Closes on Escape key. | true |
| size | enum'xs''sm''md''lg''xl''full' | Max-width of the content panel. | 'md' |
| position | enum'top''center''bottom''top-left''top-right''center-left''center-right''bottom-left''botom-right' | Vertical alignment on the viewport. | 'center' |
| density | enum'none''compact''default''comfortable' | Padding inside the content panel. | 'default' |
| rounded | enum0'xs''sm''md''lg''xl' | Border radius of the content panel. | 'md' |
| classContent | string | string[] | Class(es) applied to the inner content panel. | |
| color | string | Foreground color override (--kit-modal-fg). | |
| background | string | Background color override (--kit-modal-bg). | |
| children | Snippet | Modal content. | |
| space | string | Add border space to viewport override (--kit-modal-space). | |
| elevation | ElevationStateenum'0''1''2''3''4''5' | Add shadow effect. | '2' |
Complement the use of kit:modal with Dialog for confirmations or Popover for light details.
