Dialog
Modal window for a focused task. Content behind is inert; Esc, the X or a click outside closes it.
import { Button } from "@/components/ui/button";import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog";import { Input } from "@/components/ui/input";
export default function Demo() { return ( <Dialog> <DialogTrigger render={<Button variant="outline" />}> Edit profile </DialogTrigger> <DialogContent showCloseButton> <DialogHeader> <DialogTitle>Edit profile</DialogTitle> <DialogDescription> Shown on your indexes and in the feed. </DialogDescription> </DialogHeader> <div className="grid gap-3 text-[13px]"> <div className="grid gap-1.5"> <label htmlFor="dialog-name">Display name</label> <Input id="dialog-name" defaultValue="Dewi Lestari" /> </div> <div className="grid gap-1.5"> <label htmlFor="dialog-handle">Handle</label> <Input id="dialog-handle" defaultValue="@dewi" /> </div> </div> <DialogFooter> <DialogClose render={<Button variant="outline" />}> Cancel </DialogClose> <Button>Save changes</Button> </DialogFooter> </DialogContent> </Dialog> );}<script setup lang="ts">import { Button } from "@/components/ui/button";import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog";import { Input } from "@/components/ui/input";</script>
<template> <Dialog> <DialogTrigger as-child> <Button variant="outline">Edit profile</Button> </DialogTrigger> <DialogContent show-close-button> <DialogHeader> <DialogTitle>Edit profile</DialogTitle> <DialogDescription>Shown on your indexes and in the feed.</DialogDescription> </DialogHeader> <div class="grid gap-3 text-[13px]"> <div class="grid gap-1.5"> <label for="dialog-name">Display name</label> <Input id="dialog-name" default-value="Dewi Lestari" /> </div> <div class="grid gap-1.5"> <label for="dialog-handle">Handle</label> <Input id="dialog-handle" default-value="@dewi" /> </div> </div> <DialogFooter> <DialogClose as-child> <Button variant="outline">Cancel</Button> </DialogClose> <Button>Save changes</Button> </DialogFooter> </DialogContent> </Dialog></template><script lang="ts"> import { Button } from "$lib/components/ui/button"; import * as Dialog from "$lib/components/ui/dialog"; import { Input } from "$lib/components/ui/input";</script>
<Dialog.Root> <Dialog.Trigger> {#snippet child({ props })} <Button variant="outline" {...props}>Edit profile</Button> {/snippet} </Dialog.Trigger> <Dialog.Content showCloseButton> <Dialog.Header> <Dialog.Title>Edit profile</Dialog.Title> <Dialog.Description>Shown on your indexes and in the feed.</Dialog.Description> </Dialog.Header> <div class="grid gap-3 text-[13px]"> <div class="grid gap-1.5"> <label for="dialog-name">Display name</label> <Input id="dialog-name" value="Dewi Lestari" /> </div> <div class="grid gap-1.5"> <label for="dialog-handle">Handle</label> <Input id="dialog-handle" value="@dewi" /> </div> </div> <Dialog.Footer> <Dialog.Close> {#snippet child({ props })} <Button variant="outline" {...props}>Cancel</Button> {/snippet} </Dialog.Close> <Button>Save changes</Button> </Dialog.Footer> </Dialog.Content></Dialog.Root>Installation
Section titled “Installation”npx shadcn@latest add @edmi-ui/dialogpnpm dlx shadcn@latest add @edmi-ui/dialogyarn dlx shadcn@latest add @edmi-ui/dialogbunx shadcn@latest add @edmi-ui/dialogPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Install the dependencies:
Terminal window npm install @base-ui/reactTerminal window pnpm add @base-ui/reactTerminal window yarn add @base-ui/reactTerminal window bun add @base-ui/reactAdd the Edmi components this one builds on:
button,elevation.Copy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-vue@latest add @edmi-ui/dialogpnpm dlx shadcn-vue@latest add @edmi-ui/dialogyarn dlx shadcn-vue@latest add @edmi-ui/dialogbunx shadcn-vue@latest add @edmi-ui/dialogPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Install the dependencies:
Terminal window npm install reka-ui @vueuse/coreTerminal window pnpm add reka-ui @vueuse/coreTerminal window yarn add reka-ui @vueuse/coreTerminal window bun add reka-ui @vueuse/coreAdd the Edmi components this one builds on:
button,elevation.Copy the code from Component source into your project and update the import paths to match your aliases.
npx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/dialog.jsonpnpm dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/dialog.jsonyarn dlx shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/dialog.jsonbunx --bun shadcn-svelte@latest add https://viandwi24.github.io/edmi-ui/r/svelte/dialog.jsonPick your package manager above; the choice is remembered. Add the @edmi-ui registry first, see Getting started.
Add the Edmi components this one builds on:
button,elevation.Copy the code from Component source into your project and update the import paths to match your aliases.
import { Button } from "@/components/ui/button";import { Dialog, DialogTrigger } from "@/components/ui/dialog";
<Dialog> <DialogTrigger render={<Button variant="outline" />}> Edit profile </DialogTrigger> {/* … */}</Dialog><script setup lang="ts">import { Button } from "@/components/ui/button";import { Dialog, DialogTrigger } from "@/components/ui/dialog";</script>
<template> <Dialog> <DialogTrigger as-child> <Button variant="outline">Edit profile</Button> </DialogTrigger> <!-- … --> </Dialog></template><script lang="ts"> import * as Dialog from "$lib/components/ui/dialog"; import { Button } from "$lib/components/ui/button";</script>
<Dialog.Root> <Dialog.Trigger> {#snippet child({ props })} <Button variant="outline" {...props}>Edit profile</Button> {/snippet} </Dialog.Trigger> <!-- … --></Dialog.Root>Component source
Section titled “Component source”"use client";
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";import { cn } from "cn";import type * as React from "react";import { XIcon } from "@phosphor-icons/react";
import { Button } from "@/registry/edmi/ui/button";import { type Elevation, SurfaceProvider, useElevation,} from "@/registry/edmi/ui/elevation";
// ✦ depth (v4): overlay role. Natural level is floating in layered mode; flat otherwise.const overlayElevation = { sunken: "", flat: "", raised: "border-transparent shadow-raised", floating: "border-transparent shadow-floating",};
function Dialog({ ...props }: DialogPrimitive.Root.Props) { return <DialogPrimitive.Root data-slot="dialog" {...props} />;}
function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) { return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;}
function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) { return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;}
function DialogClose({ ...props }: DialogPrimitive.Close.Props) { return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;}
function DialogOverlay({ className, ...props}: DialogPrimitive.Backdrop.Props) { return ( <DialogPrimitive.Backdrop data-slot="dialog-overlay" className={cn( // `--overlay` scrim, no backdrop blur. "fixed inset-0 isolate z-50 bg-overlay transition-opacity duration-150 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0", className, )} {...props} /> );}
function DialogContent({ className, children, showCloseButton = true, elevation, ...props}: DialogPrimitive.Popup.Props & { showCloseButton?: boolean; /** ✦ depth: flat 0, raised +1 (bevel), floating +2 (bevel + drop). */ elevation?: Elevation;}) { const level = useElevation(elevation, "overlay"); return ( <DialogPortal> <DialogOverlay /> <DialogPrimitive.Popup data-slot="dialog-content" className={cn( // recipes.surface.dialog: flat — 2xl radius, 22px padding. `elevation` adds the bevel / drop. "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-2xl border border-border bg-popover p-[22px] text-sm text-popover-foreground outline-none transition-[opacity,scale] duration-150 data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0 sm:max-w-md", overlayElevation[level], className, )} {...props} > <SurfaceProvider level={level}>{children}</SurfaceProvider> {showCloseButton && ( <DialogPrimitive.Close data-slot="dialog-close" render={ <Button variant="ghost" className="absolute top-3.5 right-3.5" size="icon-xs" /> } > <XIcon /> <span className="sr-only">Close</span> </DialogPrimitive.Close> )} </DialogPrimitive.Popup> </DialogPortal> );}
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="dialog-header" className={cn("flex flex-col gap-1.5", className)} {...props} /> );}
function DialogFooter({ className, showCloseButton = false, children, ...props}: React.ComponentProps<"div"> & { showCloseButton?: boolean;}) { return ( <div data-slot="dialog-footer" className={cn( "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className, )} {...props} > {children} {showCloseButton && ( <DialogPrimitive.Close render={<Button variant="outline" />}> Close </DialogPrimitive.Close> )} </div> );}
function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) { return ( <DialogPrimitive.Title data-slot="dialog-title" className={cn( "text-base leading-snug font-semibold tracking-[-0.2px]", className, )} {...props} /> );}
function DialogDescription({ className, ...props}: DialogPrimitive.Description.Props) { return ( <DialogPrimitive.Description data-slot="dialog-description" className={cn( "text-[13px] text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className, )} {...props} /> );}
export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger,};<script setup lang="ts">import type { DialogRootEmits, DialogRootProps } from 'reka-ui'import { DialogRoot, useForwardPropsEmits } from 'reka-ui'
const props = defineProps<DialogRootProps>()const emits = defineEmits<DialogRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)</script>
<template> <DialogRoot v-slot="slotProps" data-slot="dialog" v-bind="forwarded" > <slot v-bind="slotProps" /> </DialogRoot></template><script setup lang="ts">import type { DialogCloseProps } from 'reka-ui'import { DialogClose } from 'reka-ui'
const props = defineProps<DialogCloseProps>()</script>
<template> <DialogClose data-slot="dialog-close" v-bind="props" > <slot /> </DialogClose></template><script setup lang="ts">import type { DialogContentEmits, DialogContentProps } from 'reka-ui'import type { HTMLAttributes } from 'vue'import { X } from '@lucide/vue'import { reactiveOmit } from '@vueuse/core'import { DialogClose, DialogContent, DialogPortal, useForwardPropsEmits,} from 'reka-ui'import { Button } from '@/registry/edmi/ui/button'import { cn } from '@/registry/edmi/lib/utils'import { type Elevation, provideSurface, useElevation } from '@/registry/edmi/ui/elevation'import DialogOverlay from './DialogOverlay.vue'
defineOptions({ inheritAttrs: false,})
const props = withDefaults(defineProps<DialogContentProps & { class?: HTMLAttributes['class'], showCloseButton?: boolean, elevation?: Elevation }>(), { showCloseButton: true, elevation: undefined,})const emits = defineEmits<DialogContentEmits>()
// ✦ depth (v4): overlay role. Natural level is floating in layered mode; flat otherwise.const overlayElevation = { sunken: '', flat: '', raised: 'border-transparent shadow-raised', floating: 'border-transparent shadow-floating',}const level = useElevation(() => props.elevation, 'overlay')provideSurface(() => level.value)
const delegatedProps = reactiveOmit(props, 'class', 'showCloseButton', 'elevation')
const forwarded = useForwardPropsEmits(delegatedProps, emits)</script>
<template> <DialogPortal> <DialogOverlay /> <DialogContent data-slot="dialog-content" v-bind="{ ...$attrs, ...forwarded }" :class=" cn( // recipes.surface.dialog: 2xl radius, 22px padding, flat by default; `elevation` ✦ adds the bevel / drop. 'fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-2xl border border-border bg-popover p-[22px] text-sm text-popover-foreground outline-none duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:max-w-md', overlayElevation[level], props.class, )" > <slot />
<DialogClose v-if="showCloseButton" as-child > <Button data-slot="dialog-close" variant="ghost" size="icon-xs" class="absolute top-3.5 right-3.5" > <X /> <span class="sr-only">Close</span> </Button> </DialogClose> </DialogContent> </DialogPortal></template><script setup lang="ts">import type { DialogDescriptionProps } from 'reka-ui'import type { HTMLAttributes } from 'vue'import { reactiveOmit } from '@vueuse/core'import { DialogDescription, useForwardProps } from 'reka-ui'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)</script>
<template> <DialogDescription data-slot="dialog-description" v-bind="forwardedProps" :class="cn('text-[13px] text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground', props.class)" > <slot /> </DialogDescription></template><script setup lang="ts">import type { HTMLAttributes } from 'vue'import { DialogClose } from 'reka-ui'import { Button } from '@/registry/edmi/ui/button'import { cn } from '@/registry/edmi/lib/utils'
const props = withDefaults(defineProps<{ class?: HTMLAttributes['class'] showCloseButton?: boolean}>(), { showCloseButton: false,})</script>
<template> <div data-slot="dialog-footer" :class="cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', props.class)" > <slot /> <DialogClose v-if="showCloseButton" as-child> <Button variant="outline"> Close </Button> </DialogClose> </div></template><script setup lang="ts">import type { HTMLAttributes } from 'vue'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<{ class?: HTMLAttributes['class']}>()</script>
<template> <div data-slot="dialog-header" :class="cn('flex flex-col gap-1.5', props.class)" > <slot /> </div></template><script setup lang="ts">import type { DialogOverlayProps } from 'reka-ui'import type { HTMLAttributes } from 'vue'import { reactiveOmit } from '@vueuse/core'import { DialogOverlay } from 'reka-ui'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<DialogOverlayProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')</script>
<template> <DialogOverlay data-slot="dialog-overlay" v-bind="delegatedProps" :class="cn('fixed inset-0 isolate z-50 bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', props.class)" > <slot /> </DialogOverlay></template><script setup lang="ts">import type { DialogTitleProps } from 'reka-ui'import type { HTMLAttributes } from 'vue'import { reactiveOmit } from '@vueuse/core'import { DialogTitle, useForwardProps } from 'reka-ui'import { cn } from '@/registry/edmi/lib/utils'
const props = defineProps<DialogTitleProps & { class?: HTMLAttributes['class'] }>()
const delegatedProps = reactiveOmit(props, 'class')
const forwardedProps = useForwardProps(delegatedProps)</script>
<template> <DialogTitle data-slot="dialog-title" v-bind="forwardedProps" :class="cn('text-base leading-snug font-semibold tracking-[-0.2px]', props.class)" > <slot /> </DialogTitle></template><script setup lang="ts">import type { DialogTriggerProps } from 'reka-ui'import { DialogTrigger } from 'reka-ui'
const props = defineProps<DialogTriggerProps>()</script>
<template> <DialogTrigger data-slot="dialog-trigger" v-bind="props" > <slot /> </DialogTrigger></template>export { default as Dialog } from "./Dialog.vue";export { default as DialogClose } from "./DialogClose.vue";export { default as DialogContent } from "./DialogContent.vue";export { default as DialogDescription } from "./DialogDescription.vue";export { default as DialogFooter } from "./DialogFooter.vue";export { default as DialogHeader } from "./DialogHeader.vue";export { default as DialogOverlay } from "./DialogOverlay.vue";export { default as DialogTitle } from "./DialogTitle.vue";export { default as DialogTrigger } from "./DialogTrigger.vue";<script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui";
let { open = $bindable(false), ...restProps }: DialogPrimitive.RootProps = $props();</script>
<DialogPrimitive.Root bind:open {...restProps} /><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui";
let { ref = $bindable(null), type = "button", ...restProps }: DialogPrimitive.CloseProps = $props();</script>
<DialogPrimitive.Close bind:ref data-slot="dialog-close" {type} {...restProps} /><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui"; import XIcon from "phosphor-svelte/lib/X"; import { Button } from "$lib/registry/ui/button/index.js"; import { cn, type WithoutChildrenOrChild } from "$lib/utils.js"; import { type Elevation, setSurface, useElevation } from "$lib/registry/ui/elevation/index.js"; import DialogOverlay from "./dialog-overlay.svelte"; import DialogPortal from "./dialog-portal.svelte"; import type { Snippet } from "svelte"; import type { ComponentProps } from "svelte";
let { ref = $bindable(null), class: className, portalProps, children, showCloseButton = true, elevation = "auto", ...restProps }: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & { portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DialogPortal>>; children: Snippet; showCloseButton?: boolean; /** ✦ depth: flat 0, raised +1 (bevel), floating +2 (bevel + drop). */ elevation?: Elevation; } = $props();
// ✦ depth (v4): overlay role. Natural level is floating in layered mode; flat otherwise. const overlayElevation = { sunken: "", flat: "", raised: "border-transparent shadow-raised", floating: "border-transparent shadow-floating", }; const level = useElevation(() => elevation, "overlay"); setSurface(() => level.current);</script>
<DialogPortal {...portalProps}> <DialogOverlay /> <DialogPrimitive.Content bind:ref data-slot="dialog-content" class={cn( // recipes.surface.dialog (flat); elevation ✦ adds the bevel / drop. "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-2xl border border-border bg-popover p-[22px] text-sm text-popover-foreground outline-none duration-150 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:max-w-md", overlayElevation[level.current], className )} {...restProps} > {@render children?.()} {#if showCloseButton} <DialogPrimitive.Close data-slot="dialog-close"> {#snippet child({ props })} <Button variant="ghost" class="absolute top-3.5 right-3.5" size="icon-xs" {...props}> <XIcon /> <span class="sr-only">Close</span> </Button> {/snippet} </DialogPrimitive.Close> {/if} </DialogPrimitive.Content></DialogPortal><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui"; import { cn } from "$lib/utils.js";
let { ref = $bindable(null), class: className, ...restProps }: DialogPrimitive.DescriptionProps = $props();</script>
<DialogPrimitive.Description bind:ref data-slot="dialog-description" class={cn( "text-[13px] text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground", className )} {...restProps}/><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui"; import { Button } from "$lib/registry/ui/button/index.js"; import { cn, type WithElementRef } from "$lib/utils.js"; import type { HTMLAttributes } from "svelte/elements";
let { ref = $bindable(null), class: className, children, showCloseButton = false, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> & { showCloseButton?: boolean; } = $props();</script>
<div bind:this={ref} data-slot="dialog-footer" class={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)} {...restProps}> {@render children?.()} {#if showCloseButton} <DialogPrimitive.Close> {#snippet child({ props })} <Button variant="outline" {...props}>Close</Button> {/snippet} </DialogPrimitive.Close> {/if}</div><script lang="ts"> import { cn, type WithElementRef } from "$lib/utils.js"; import type { HTMLAttributes } from "svelte/elements";
let { ref = $bindable(null), class: className, children, ...restProps }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();</script>
<div bind:this={ref} data-slot="dialog-header" class={cn("flex flex-col gap-1.5", className)} {...restProps}> {@render children?.()}</div><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui"; import { cn } from "$lib/utils.js";
let { ref = $bindable(null), class: className, ...restProps }: DialogPrimitive.OverlayProps = $props();</script>
<DialogPrimitive.Overlay bind:ref data-slot="dialog-overlay" class={cn( // `--overlay` scrim, no backdrop blur. "fixed inset-0 isolate z-50 bg-overlay data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", className )} {...restProps}/><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui";
let { ...restProps }: DialogPrimitive.PortalProps = $props();</script>
<DialogPrimitive.Portal {...restProps} /><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui"; import { cn } from "$lib/utils.js";
let { ref = $bindable(null), class: className, ...restProps }: DialogPrimitive.TitleProps = $props();</script>
<DialogPrimitive.Title bind:ref data-slot="dialog-title" class={cn("text-base leading-snug font-semibold tracking-[-0.2px]", className)} {...restProps}/><script lang="ts"> import { Dialog as DialogPrimitive } from "bits-ui";
let { ref = $bindable(null), type = "button", ...restProps }: DialogPrimitive.TriggerProps = $props();</script>
<DialogPrimitive.Trigger bind:ref data-slot="dialog-trigger" {type} {...restProps} />import Root from "./dialog.svelte";import Close from "./dialog-close.svelte";import Content from "./dialog-content.svelte";import Description from "./dialog-description.svelte";import Footer from "./dialog-footer.svelte";import Header from "./dialog-header.svelte";import Overlay from "./dialog-overlay.svelte";import Portal from "./dialog-portal.svelte";import Title from "./dialog-title.svelte";import Trigger from "./dialog-trigger.svelte";
export { Close, Close as DialogClose, Content, Content as DialogContent, Description, Description as DialogDescription, Footer, Footer as DialogFooter, Header, Header as DialogHeader, Overlay, Overlay as DialogOverlay, Portal, Portal as DialogPortal, Root, // Root as Dialog, Title, Title as DialogTitle, Trigger, Trigger as DialogTrigger,};Elevation ✦
Section titled “Elevation ✦”See the Elevation guide for the levels, roles and layered mode.
Flat by default. On DialogContent, raised (+1) adds the bevel and floating (+2) the bevel plus one soft drop (the natural level in layered mode).
import { Button } from "@/components/ui/button";import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog";import { Input } from "@/components/ui/input";
export default function Demo() { return ( <Dialog> <DialogTrigger render={<Button variant="outline" />}> Edit profile </DialogTrigger> <DialogContent elevation="floating" showCloseButton> <DialogHeader> <DialogTitle>Edit profile</DialogTitle> <DialogDescription> Shown on your indexes and in the feed. </DialogDescription> </DialogHeader> <div className="grid gap-3 text-[13px]"> <div className="grid gap-1.5"> <label htmlFor="dialog-name">Display name</label> <Input id="dialog-name" defaultValue="Dewi Lestari" /> </div> <div className="grid gap-1.5"> <label htmlFor="dialog-handle">Handle</label> <Input id="dialog-handle" defaultValue="@dewi" /> </div> </div> <DialogFooter> <DialogClose render={<Button variant="outline" />}> Cancel </DialogClose> <Button>Save changes</Button> </DialogFooter> </DialogContent> </Dialog> );}<script setup lang="ts">import { Button } from "@/components/ui/button";import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog";</script>
<template> <Dialog> <DialogTrigger as-child> <Button variant="outline">Open floating dialog</Button> </DialogTrigger> <DialogContent elevation="floating"> <DialogHeader> <DialogTitle>Floating dialog</DialogTitle> <DialogDescription>Bevel plus one soft drop (+2).</DialogDescription> </DialogHeader> <DialogFooter> <DialogClose as-child> <Button variant="outline">Cancel</Button> </DialogClose> <Button>Save</Button> </DialogFooter> </DialogContent> </Dialog></template><script lang="ts"> import { Button } from "$lib/components/ui/button"; import * as Dialog from "$lib/components/ui/dialog";</script>
<Dialog.Root> <Dialog.Trigger> {#snippet child({ props })} <Button variant="outline" {...props}>Open floating dialog</Button> {/snippet} </Dialog.Trigger> <Dialog.Content elevation="floating"> <Dialog.Header> <Dialog.Title>Floating dialog</Dialog.Title> <Dialog.Description>Bevel plus one soft drop (+2).</Dialog.Description> </Dialog.Header> <Dialog.Footer> <Dialog.Close> {#snippet child({ props })} <Button variant="outline" {...props}>Cancel</Button> {/snippet} </Dialog.Close> <Button>Save</Button> </Dialog.Footer> </Dialog.Content></Dialog.Root>| Prop | Type | Default |
|---|---|---|
DialogContent showCloseButton |
boolean |
true |
DialogFooter showCloseButton |
boolean |
false |
Dialog open / onOpenChange |
controlled state | uncontrolled |
elevation |
"auto" | "sunken" | "flat" | "raised" | "floating" |
"auto" |
Parts: Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, DialogOverlay, DialogPortal.
✦ Edmi additions
Section titled “✦ Edmi additions”--overlayscrim without backdrop blur; flat by default;elevationadds the bevel / drop.