A modal dialog for displaying content and actions.
Hello Skeleton
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
tsx
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';import { XIcon } from 'lucide-react';export default function Default() { // The following animation is optional. // This may also be included inline. const animation = 'transition transition-discrete opacity-0 translate-y-[100px] starting:data-[state=open]:opacity-0 starting:data-[state=open]:translate-y-[100px] data-[state=open]:opacity-100 data-[state=open]:translate-y-0'; 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 p-4"> <Dialog.Content className={`card bg-surface-100-900 w-full max-w-xl p-4 space-y-4 shadow-xl ${animation}`}> <header className="flex justify-between items-center"> <Dialog.Title className="text-lg font-bold">Hello Skeleton</Dialog.Title> <Dialog.CloseTrigger className="btn-icon hover:preset-tonal"> <XIcon className="size-4" /> </Dialog.CloseTrigger> </header> <Dialog.Description> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </Dialog.Description> <footer className="flex justify-end gap-2"> <Dialog.CloseTrigger className="btn preset-tonal">Cancel</Dialog.CloseTrigger> <button type="button" className="btn preset-filled"> Save </button> </footer> </Dialog.Content> </Dialog.Positioner> </Portal> </Dialog> );}
Hello Skeleton
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
svelte
<script lang="ts"> import { XIcon } from '@lucide/svelte'; import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte'; // The following animation is optional. // This may also be included inline. const animation = 'transition transition-discrete opacity-0 translate-y-[100px] starting:data-[state=open]:opacity-0 starting:data-[state=open]:translate-y-[100px] data-[state=open]:opacity-100 data-[state=open]:translate-y-0';</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 p-4"> <Dialog.Content class="card bg-surface-100-900 w-full max-w-xl p-4 space-y-4 shadow-xl {animation}"> <header class="flex justify-between items-center"> <Dialog.Title class="text-lg font-bold">Hello Skeleton</Dialog.Title> <Dialog.CloseTrigger class="btn-icon hover:preset-tonal"> <XIcon class="size-4" /> </Dialog.CloseTrigger> </header> <Dialog.Description> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </Dialog.Description> <footer class="flex justify-end gap-2"> <Dialog.CloseTrigger class="btn preset-tonal">Cancel</Dialog.CloseTrigger> <button type="button" class="btn preset-filled">Save</button> </footer> </Dialog.Content> </Dialog.Positioner> </Portal></Dialog>
Breaking convention in Skeleton, this component is provided “headless”. Meaning no default styles are applied out of the box. This ensures you retain full control of all styling for maximum flexibility.
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.
If desired, you can disable click to close interactions for the backdrop.
TIP: use this sparingly, as this can trap users in this experience without a dedicated close action.
Dialog Title
This dialog will only close with the Close button or via programmatic controls.
tsx
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> );}
Dialog Title
This dialog will only close with the Close button or via programmatic controls.
svelte
<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>
Drawer
This example repurposes the Dialog for use as a side-panel Drawer. This pairs well with the Navigation Sidebar .
Drawer
A slide out drawer panel.
tsx
import { Dialog, Portal } from '@skeletonlabs/skeleton-react';import { XIcon } from 'lucide-react';export default function Drawer() { // The following animations are optional. // These may also be included inline. const animBackdrop = 'transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100'; const animModal = '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'; 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 ${animBackdrop}`} /> <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 ${animModal}`}> <header className="flex justify-between items-center"> <Dialog.Title className="text-2xl font-bold">Drawer</Dialog.Title> <Dialog.CloseTrigger className="btn-icon preset-tonal"> <XIcon /> </Dialog.CloseTrigger> </header> <p>A slide out drawer panel.</p> </Dialog.Content> </Dialog.Positioner> </Portal> </Dialog> );}
Drawer
A slide out drawer panel.
svelte
<script lang="ts"> import { XIcon } from '@lucide/svelte'; import { Dialog, Portal } from '@skeletonlabs/skeleton-svelte'; // The following animations are optional. // These may also be included inline. const animBackdrop = 'transition transition-discrete opacity-0 starting:data-[state=open]:opacity-0 data-[state=open]:opacity-100'; const animModal = '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';</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 {animBackdrop}" /> <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 {animModal}"> <header class="flex justify-between items-center"> <Dialog.Title class="text-2xl font-bold">Drawer</Dialog.Title> <Dialog.CloseTrigger class="btn-icon preset-tonal"> <XIcon /> </Dialog.CloseTrigger> </header> <p>A slide out drawer panel.</p> </Dialog.Content> </Dialog.Positioner> </Portal></Dialog>
Z-Index
By default Skeleton does 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.
Setting Z-Index
This dialog will have a z-index value of 50.
tsx
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> );}
Setting Z-Index
This dialog will have a z-index value of 50.
svelte
<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>
Direction
Set the text direction (ltr or rtl) using the dir prop.
Hello World
This is an example of a basic dialog.
tsx
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> );}
Hello World
This is an example of a basic dialog.
svelte
<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>
Anatomy
Here’s an overview of how the Dialog component is structured in code: