Dialog
Installation
npx @mielui/svelte add dialogyarn dlx @mielui/svelte add dialogbunx @mielui/svelte add dialogUsage
Bind open on Root to open or close the dialog from another control. onOpenChange runs when the dialog opens or closes itself; setting the bound value does not call it. Each Root keeps its own state.
Include a Title, or give Content an aria-label. Description is optional. Focus, Escape, and outside presses are coordinated with nested overlays, so the topmost layer closes first.
The theme's chrome.borders setting chooses single framing, the default, or double framing around the panel.
<script lang="ts">
import * as Dialog from '@mielui/svelte/components/dialog';
import Kbd from '@mielui/svelte/components/kbd';
let open = $state(false);
</script>
<Dialog.Root bind:open>
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Title</Dialog.Title>
</Dialog.Header>
<Dialog.Footer>
<Dialog.Close>Cancel <Kbd shortcut="esc" /></Dialog.Close>
<Dialog.Confirm>Save <Kbd shortcut="enter" /></Dialog.Confirm>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>Examples
Form in a dialog
A compact dialog with an icon beside the title, one field, and shortcut hints on the actions.
Basic
Nested
With select
A Select inside a dialog keeps its own layer: Escape closes the menu first and only then the dialog.
Compact
Large
Wide
Glass surface
Set surface="glass" on Dialog.Content for a translucent background with blur. Omit surface to inherit --mielui-surface from your theme, or set surface="solid" to override it. The glass surface keeps an opaque fallback when backdrop filtering is unavailable and respects reduced-transparency preferences.
Dismissal
A dialog closes four ways: the corner button, Escape, a press outside the panel, and its own Close or Confirm buttons. Content has a switch for each of the first three. showClose={false} removes the corner button, allowEscape={false} ignores Escape, and allowClickOutside={false} ignores presses on the backdrop.
Turn all three off when the person has to make a choice, and leave at least one button in the footer so they are never stuck.
No plan chosen yet
Action buttons
Close and Confirm close the dialog after their onclick runs. Call event.preventDefault() inside onclick to keep it open, then set open to false yourself when the work is done. Pair that with loading and labels so the button shows progress and ignores a second click.
Trigger, Close and Confirm are built on Button, so they accept its props. variant and size change the look, disabled blocks activation, and href renders a link. loading shows a spinner and ignores clicks, and labels sets the text for each state. unstyled removes the Button classes so class alone styles the part. onclick and onkeydown run before the part does its own work. Confirm defaults to the primary variant and Close to ghost.
Destructive dialogs
Set error on Root when confirming is destructive. Confirm switches to the destructive variant unless you pass your own variant, and browsers that tint their toolbar from the page's theme color turn it red while the dialog is open.
Styling the layers
Content renders three nested layers and takes a class for each. overlayClass styles the backdrop, class the dialog panel, and surfaceClass the inner surface that holds your parts. The style attribute lands on the panel too.
Header, Title, Description, Body and Footer render their children and accept class and style like any element.
Labels
Built-in text is English. Pass a labels object to Root to translate the accessible name of the corner close button. DialogLabels types it; every key is optional and omitted keys keep their English default.
<Dialog.Root labels={{ close: 'Fermer' }}>
<Dialog.Trigger>Ouvrir</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Renommer le projet</Dialog.Title>
</Dialog.Header>
</Dialog.Content>
</Dialog.Root>API reference
Dialog.Root
Controls dialog state.
labelsDialogLabelsOverrides the built-in text and accessible names. Every key is optional and English is the fallback.
openBindablebooleanWhether it is open. Bind it to control the state from outside.
Default
falseonOpenChange((open: boolean) => void)Called with the new state whenever it opens or closes.
errorbooleanMarks the dialog as destructive. Confirm defaults to the destructive variant, and browsers that tint their chrome from the theme color turn it red while the dialog is open.
Default
falsechildrenSnippet<[]>Content rendered inside.
Dialog.Body
Renders the dialog body.
classstringClasses added to the element.
childrenSnippet<[]>Content rendered inside.
Dialog.Close
Closes the dialog.
disabledbooleanPrevents activation. A disabled link loses its destination and is skipped by Tab.
variantButtonVariantVisual style. Choose it for what the action means, not for decoration.
size"sm" | "md" | "lg" | "icon"Control height.
iconis a square button for a single icon.childrenSnippet<[]>Content rendered inside.
elementBindableHTMLButtonElement | HTMLAnchorElementBindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site:
unstyledbooleanSkip the variant/size base classes and render with
classalone.statusButtonStatusControlled visual state. Loading remains focusable and refuses activation.
loadingbooleanConvenience alias for
status="loading".labelsButtonLabelsOverrides the built-in text and accessible names. Every key is optional and English is the fallback.
onclick((event: MouseEvent) => void)Called when the button is activated. Loading and disabled buttons do not call it.
onkeydown((event: KeyboardEvent) => void)Called on key down, before the button handles the key itself.
hrefstringRenders a link to this address instead of a button.
Dialog.Confirm
Confirms and closes the dialog.
disabledbooleanPrevents activation. A disabled link loses its destination and is skipped by Tab.
variantButtonVariantVisual style. Choose it for what the action means, not for decoration.
size"sm" | "md" | "lg" | "icon"Control height.
iconis a square button for a single icon.childrenSnippet<[]>Content rendered inside.
elementBindableHTMLButtonElement | HTMLAnchorElementBindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site:
unstyledbooleanSkip the variant/size base classes and render with
classalone.statusButtonStatusControlled visual state. Loading remains focusable and refuses activation.
loadingbooleanConvenience alias for
status="loading".labelsButtonLabelsOverrides the built-in text and accessible names. Every key is optional and English is the fallback.
onclick((event: MouseEvent) => void)Called when the button is activated. Loading and disabled buttons do not call it.
onkeydown((event: KeyboardEvent) => void)Called on key down, before the button handles the key itself.
hrefstringRenders a link to this address instead of a button.
Dialog.Content
Renders the dialog surface.
surface"solid" | "glass"Surface treatment. Omit it to inherit
--mielui-surfacefrom the theme.allowClickOutsidebooleanCloses when the pointer is pressed outside it. Set false to keep it open until it is dismissed another way.
Default
trueallowEscapebooleanLets Escape dismiss the dialog.
Default
trueoverlayClassstringClasses for the backdrop.
Default
''surfaceClassstringClasses for the inner surface.
Default
''showClosebooleanShows the close button in the corner.
Default
truesizeDialogSizeMaximum width of the panel. Defaults to
lg.Default
'lg'classstringClasses added to the element.
childrenSnippet<[]>Content rendered inside.
Dialog.Description
Renders the dialog description.
classstringClasses added to the element.
childrenSnippet<[]>Content rendered inside.
Dialog.Footer
Groups dialog actions.
classstringClasses added to the element.
childrenSnippet<[]>Content rendered inside.
Dialog.Header
Groups dialog heading content.
classstringClasses added to the element.
childrenSnippet<[]>Content rendered inside.
Dialog.Title
Renders the dialog title.
classstringClasses added to the element.
childrenSnippet<[]>Content rendered inside.
Dialog.Trigger
Opens the dialog.
disabledbooleanPrevents activation. A disabled link loses its destination and is skipped by Tab.
variantButtonVariantVisual style. Choose it for what the action means, not for decoration.
size"sm" | "md" | "lg" | "icon"Control height.
iconis a square button for a single icon.childrenSnippet<[]>Content rendered inside.
elementBindableHTMLButtonElement | HTMLAnchorElementBindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site:
unstyledbooleanSkip the variant/size base classes and render with
classalone.statusButtonStatusControlled visual state. Loading remains focusable and refuses activation.
loadingbooleanConvenience alias for
status="loading".labelsButtonLabelsOverrides the built-in text and accessible names. Every key is optional and English is the fallback.
onclick((event: MouseEvent) => void)Called when the button is activated. Loading and disabled buttons do not call it.
onkeydown((event: KeyboardEvent) => void)Called on key down, before the button handles the key itself.
hrefstringRenders a link to this address instead of a button.
pnpm dlx @mielui/svelte add dialog