Components

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.

modal.svelte
<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.

Examples of modal

position

Controls the vertical alignment of the content panel.

  • position: 'top' | 'center' | 'bottom' = 'center'
modal.svelte
<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'
modal.svelte
<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
modal.svelte
<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

propstypedescriptiondefault
ref $bindableHTMLElementBindable reference to the rendered DOM element.null
s-classenum'string''array''object'Sets className on modal.
s-styleenum'string''array''object'Sets styles on modal.
open $bindablebooleanControls visibility.false
persistentbooleanPrevents closing on Escape.false
containbooleanPositions relative to parent instead of viewport.false
closeWithEscbooleanCloses on Escape key.true
sizeenum'xs''sm''md''lg''xl''full'Max-width of the content panel.'md'
positionenum'top''center''bottom''top-left''top-right''center-left''center-right''bottom-left''botom-right'Vertical alignment on the viewport.'center'
densityenum'none''compact''default''comfortable'Padding inside the content panel.'default'
roundedenum0'xs''sm''md''lg''xl'Border radius of the content panel.'md'
classContentstring | string[]Class(es) applied to the inner content panel.
colorstringForeground color override (--kit-modal-fg).
backgroundstringBackground color override (--kit-modal-bg).
childrenSnippetModal content.
spacestringAdd border space to viewport override (--kit-modal-space).
elevationElevationStateenum'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.