<script lang="ts">
import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
</script>
<Dialog>
<Dialog.Trigger class="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop class="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner class="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content class="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title class="text-2xl font-bold">Hello World</Dialog.Title>
<Dialog.Description>This is an example of a basic dialog.</Dialog.Description>
<Dialog.CloseTrigger class="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';
export default function Default() {
return (
<Dialog>
<Dialog.Trigger className="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop className="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner className="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content className="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title className="text-2xl font-bold">Hello World</Dialog.Title>
<Dialog.Description>This is an example of a basic dialog.</Dialog.Description>
<Dialog.CloseTrigger className="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
);
}
Alert Dialog
The alertdialog role enables assistive technologies and browsers to distinguish alert dialogs from other dialogs so they have the option of giving alert dialogs special treatment, such as playing a system alert sound.
<script lang="ts">
import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
</script>
<Dialog role="alertdialog">
<Dialog.Trigger class="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop class="fixed inset-0 z-50 bg-error-50-950/50" />
<Dialog.Positioner class="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content class="card preset-filled-error-500 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title class="text-2xl font-bold">Alert</Dialog.Title>
<Dialog.Description>Something important has happened!</Dialog.Description>
<Dialog.CloseTrigger class="btn preset-tonal-error">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';
export default function AlertDialog() {
return (
<Dialog role="alertdialog">
<Dialog.Trigger className="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop className="fixed inset-0 z-50 bg-error-50-950/50" />
<Dialog.Positioner className="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content className="card preset-filled-error-500 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title className="text-2xl font-bold">Alert</Dialog.Title>
<Dialog.Description>Something important has happened!</Dialog.Description>
<Dialog.CloseTrigger className="btn preset-tonal-error">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
);
}
Interaction
If desired, you can disable click to close interactions for the backdrop. We recommend using this sparingly, as this traps the user in this experience.
<script lang="ts">
import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
</script>
<Dialog closeOnInteractOutside={false}>
<Dialog.Trigger class="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop class="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner class="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content class="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title class="text-2xl font-bold">Dialog Title</Dialog.Title>
<Dialog.Description>This dialog will only close with the Close button or via programmatic controls.</Dialog.Description>
<Dialog.CloseTrigger class="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';
export default function Interaction() {
return (
<Dialog closeOnInteractOutside={false}>
<Dialog.Trigger className="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop className="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner className="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content className="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title className="text-2xl font-bold">Dialog Title</Dialog.Title>
<Dialog.Description>This dialog will only close with the Close button or via programmatic controls.</Dialog.Description>
<Dialog.CloseTrigger className="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
);
}
Drawer
This example repurposes the Dialog for use as a side-panel Drawer. It also introduces basic transition animations.
This is example content for the slide out drawer panel.
<script lang="ts">
import { XIcon } from '@lucide/svelte';
import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
</script>
<Dialog>
<Dialog.Trigger class="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop
class="fixed inset-0 z-50 bg-surface-50-950/50 transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100"
/>
<Dialog.Positioner class="fixed inset-0 z-50 flex justify-start">
<Dialog.Content
class="h-screen card bg-surface-100-900 w-sm p-4 space-y-4 shadow-xl transition transition-discrete opacity-0 -translate-x-full starting:data-[state=open]:opacity-0 starting:data-[state=open]:-translate-x-full data-[state=open]:opacity-100 data-[state=open]:translate-x-0"
>
<header class="flex justify-between items-center">
<Dialog.Title class="text-2xl font-bold">Drawer Title</Dialog.Title>
<Dialog.CloseTrigger class="btn-icon preset-tonal">
<XIcon />
</Dialog.CloseTrigger>
</header>
<p>This is example content for the slide out drawer panel.</p>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
This is example content for the slide out drawer panel.
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';
import { XIcon } from 'lucide-react';
export default function Drawer() {
return (
<Dialog>
<Dialog.Trigger className="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop className="fixed inset-0 z-50 bg-surface-50-950/50 transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100" />
<Dialog.Positioner className="fixed inset-0 z-50 flex justify-start">
<Dialog.Content className="h-screen card bg-surface-100-900 w-sm p-4 space-y-4 shadow-xl transition transition-discrete opacity-0 -translate-x-full starting:data-[state=open]:opacity-0 starting:data-[state=open]:-translate-x-full data-[state=open]:opacity-100 data-[state=open]:translate-x-0">
<header className="flex justify-between items-center">
<Dialog.Title className="text-2xl font-bold">Drawer Title</Dialog.Title>
<Dialog.CloseTrigger className="btn-icon preset-tonal">
<XIcon />
</Dialog.CloseTrigger>
</header>
<p>This is example content for the slide out drawer panel.</p>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
);
}
Z-Index
By default we do not take an opinionated stance regarding z-index stacking. The result is the component can sometimes be occluded beneath other elements with a higher index. The Z-Index can controlled by applying a utility class to the Positioner component part.
<script lang="ts">
import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
</script>
<Dialog>
<Dialog.Trigger class="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop class="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner class="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content class="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title class="text-2xl font-bold">Setting Z-Index</Dialog.Title>
<Dialog.Description>This dialog will have a z-index value of 50.</Dialog.Description>
<Dialog.CloseTrigger class="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';
export default function ZIndex() {
return (
<Dialog>
<Dialog.Trigger className="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop className="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner className="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content className="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title className="text-2xl font-bold">Setting Z-Index</Dialog.Title>
<Dialog.Description>This dialog will have a z-index value of 50.</Dialog.Description>
<Dialog.CloseTrigger className="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
);
}
Direction
<script lang="ts">
import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
</script>
<Dialog dir="rtl">
<Dialog.Trigger class="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop class="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner class="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content class="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title class="text-2xl font-bold">Hello World</Dialog.Title>
<Dialog.Description>This is an example of a basic dialog.</Dialog.Description>
<Dialog.CloseTrigger class="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';
export default function Dir() {
return (
<Dialog dir="rtl">
<Dialog.Trigger className="btn preset-filled">Trigger</Dialog.Trigger>
<Portal>
<Dialog.Backdrop className="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner className="fixed inset-0 z-50 flex justify-center items-center">
<Dialog.Content className="card bg-surface-100-900 w-md p-4 space-y-2 shadow-xl">
<Dialog.Title className="text-2xl font-bold">Hello World</Dialog.Title>
<Dialog.Description>This is an example of a basic dialog.</Dialog.Description>
<Dialog.CloseTrigger className="btn preset-tonal">Close</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
);
}
Headless
Unlike most components in Skeleton, this feature is provided “headless”. This means no default styles are applied out of the box. This ensures you retain full control of all styling.
<script lang="ts">
import { SkullIcon } from '@lucide/svelte';
import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte';
</script>
<Dialog>
<Dialog.Trigger>
<SkullIcon class="size-12" />
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop class="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner class="fixed inset-0 z-50 flex justify-center items-center p-4">
<Dialog.Content>
<div class="card border border-surface-200/30 bg-surface-50-900/30 backdrop-blur-sm w-full max-w-xl p-4 space-y-4 shadow-xl">
<header class="flex justify-between items-center">
<Dialog.Title class="text-2xl font-bold">Hello Skeleton</Dialog.Title>
<Dialog.CloseTrigger class="btn-icon hover:preset-tonal">×</Dialog.CloseTrigger>
</header>
<img
class="w-full rounded-container overflow-hidden"
src="https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExNWVmbzcxanp6YmtxZ28xcXBqaXBscThsdDZ5Nm9ncWxkeWtqaHJ2bSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9dg/dn1PN6NtunfnUjUGFC/giphy.gif"
alt="Skeleton Gif"
/>
<Dialog.Description class="text-center">Three spooky skeletons!</Dialog.Description>
</div>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>

import { Dialog, Portal } from '@skeletonlabs/skeleton-react';
import { SkullIcon } from 'lucide-react';
export default function Headless() {
return (
<Dialog>
<Dialog.Trigger>
<SkullIcon className="size-12" />
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop className="fixed inset-0 z-50 bg-surface-50-950/50" />
<Dialog.Positioner className="fixed inset-0 z-50 flex justify-center items-center p-4">
<Dialog.Content>
<div className="card border border-surface-200/30 bg-surface-50-900/30 backdrop-blur-sm w-full max-w-xl p-4 space-y-4 shadow-xl">
<header className="flex justify-between items-center">
<Dialog.Title className="text-2xl font-bold">Hello Skeleton</Dialog.Title>
<Dialog.CloseTrigger className="btn-icon hover:preset-tonal">✕</Dialog.CloseTrigger>
</header>
<img
className="w-full rounded-container overflow-hidden"
src="https://media3.giphy.com/media/v1.Y2lkPTc5MGI3NjExNWVmbzcxanp6YmtxZ28xcXBqaXBscThsdDZ5Nm9ncWxkeWtqaHJ2bSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9dg/dn1PN6NtunfnUjUGFC/giphy.gif"
alt="Skeleton Gif"
/>
<Dialog.Description className="text-center">Three spooky skeletons!</Dialog.Description>
</div>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog>
);
}
API Reference
Root
| Property | Default | Type |
|---|---|---|
children | - | ReactNode |
dir | "ltr" | "ltr" | "rtl" | undefinedThe document's text/writing direction. |
role | "dialog" | "dialog" | "alertdialog" | undefinedThe dialog's role |
aria-label | - | string | undefinedHuman readable label for the dialog, in event the dialog title is not rendered |
ids | - | Partial<{ trigger: string; positioner: string; backdrop: string; content: string; closeTrigger: string; title: string; description: string; }> | undefined The ids of the elements in the dialog. Useful for composition. |
trapFocus | true | boolean | undefinedWhether to trap focus inside the dialog when it's opened |
preventScroll | true | boolean | undefinedWhether to prevent scrolling behind the dialog when it's opened |
modal | true | boolean | undefinedWhether to prevent pointer interaction outside the element and hide all content below it |
initialFocusEl | - | (() => MaybeElement) | undefinedElement to receive focus when the dialog is opened |
finalFocusEl | - | (() => MaybeElement) | undefinedElement to receive focus when the dialog is closed |
restoreFocus | - | boolean | undefinedWhether to restore focus to the element that had focus before the dialog was opened |
closeOnInteractOutside | true | boolean | undefinedWhether to close the dialog when the outside is clicked |
closeOnEscape | true | boolean | undefinedWhether to close the dialog when the escape key is pressed |
open | - | boolean | undefinedThe controlled open state of the dialog |
defaultOpen | false | boolean | undefinedThe initial open state of the dialog when rendered. Use when you don't need to control the open state of the dialog. |
onOpenChange | - | ((details: OpenChangeDetails) => void) | undefinedFunction to call when the dialog's open state changes |
getRootNode | - | (() => Node | ShadowRoot | Document) | undefinedA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. |
onEscapeKeyDown | - | ((event: KeyboardEvent) => void) | undefinedFunction called when the escape key is pressed |
onRequestDismiss | - | ((event: LayerDismissEvent) => void) | undefinedFunction called when this layer is closed due to a parent layer being closed |
onPointerDownOutside | - | ((event: PointerDownOutsideEvent) => void) | undefinedFunction called when the pointer is pressed down outside the component |
onFocusOutside | - | ((event: FocusOutsideEvent) => void) | undefinedFunction called when the focus is moved outside the component |
onInteractOutside | - | ((event: InteractOutsideEvent) => void) | undefinedFunction called when an interaction happens outside the component |
persistentElements | - | (() => Element | null)[] | undefinedReturns the persistent elements that: - should not have pointer-events disabled - should not trigger the dismiss event |
RootProvider
| Property | Default | Type |
|---|---|---|
value | - | DialogApi<PropTypes> |
children | - | ReactNode |
RootContext
| Property | Default | Type |
|---|---|---|
children | - | (dialog: DialogApi<PropTypes>) => ReactNode |
Trigger
| Property | Default | Type |
|---|---|---|
element | - | ((attributes: HTMLAttributes<"button">) => Element) | undefinedRender the element yourself |
Backdrop
| Property | Default | Type |
|---|---|---|
element | - | ((attributes: HTMLAttributes<"div">) => Element) | undefinedRender the element yourself |
Positioner
| Property | Default | Type |
|---|---|---|
element | - | ((attributes: HTMLAttributes<"div">) => Element) | undefinedRender the element yourself |
Content
| Property | Default | Type |
|---|---|---|
element | - | ((attributes: HTMLAttributes<"div">) => Element) | undefinedRender the element yourself |
Title
| Property | Default | Type |
|---|---|---|
element | - | ((attributes: HTMLAttributes<"div">) => Element) | undefinedRender the element yourself |
Description
| Property | Default | Type |
|---|---|---|
element | - | ((attributes: HTMLAttributes<"div">) => Element) | undefinedRender the element yourself |
CloseTrigger
| Property | Default | Type |
|---|---|---|
element | - | ((attributes: HTMLAttributes<"button">) => Element) | undefinedRender the element yourself |