import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Dialog.Root>
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Usage
import { Dialog } from "@chakra-ui/react"
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.CloseTrigger />
<Dialog.Header>
<Dialog.Title />
</Dialog.Header>
<Dialog.Body />
<Dialog.Footer />
</Dialog.Content>
</Dialog.Positioner>
</Dialog.Root>
Examples
Sizes
Use the size
prop to change the size of the dialog component.
import {
Button,
CloseButton,
Dialog,
For,
HStack,
Portal,
} from "@chakra-ui/react"
const Demo = () => {
return (
<HStack>
<For each={["xs", "sm", "md", "lg"]}>
{(size) => (
<Dialog.Root key={size} size={size}>
<Dialog.Trigger asChild>
<Button variant="outline" size={size}>
Open ({size})
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua.
</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)}
</For>
</HStack>
)
}
Cover
Use the size="cover"
prop to make the dialog component cover the entire screen
while revealing a small portion of the page behind.
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Dialog.Root size="cover" placement="center" motionPreset="slide-in-bottom">
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Header>
<Dialog.Body>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</Dialog.Body>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Fullscreen
Use the size="full"
prop to make the dialog component take up the entire
screen.
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Dialog.Root size="full" motionPreset="slide-in-bottom">
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Placement
Use the placement
prop to change the placement of the dialog component.
import {
Button,
CloseButton,
Dialog,
For,
HStack,
Portal,
} from "@chakra-ui/react"
const Demo = () => {
return (
<HStack wrap="wrap" gap="4">
<For each={["top", "center", "bottom"]}>
{(placement) => (
<Dialog.Root
key={placement}
placement={placement}
motionPreset="slide-in-bottom"
>
<Dialog.Trigger asChild>
<Button variant="outline">Open Dialog ({placement}) </Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua.
</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)}
</For>
</HStack>
)
}
Controlled
Use the open
and onOpenChange
prop to control the visibility of the dialog
component.
"use client"
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
import { useState } from "react"
import Lorem from "react-lorem-ipsum"
const Demo = () => {
const [open, setOpen] = useState(false)
return (
<Dialog.Root lazyMount open={open} onOpenChange={(e) => setOpen(e.open)}>
<Dialog.Trigger asChild>
<Button variant="outline">Open</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<Lorem p={2} />
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Store
An alternative way to control the dialog is to use the RootProvider
component
and the useDialog
store hook.
This way you can access the dialog state and methods from outside the dialog.
"use client"
import {
Button,
CloseButton,
Dialog,
Portal,
useDialog,
} from "@chakra-ui/react"
const Demo = () => {
const dialog = useDialog()
return (
<Dialog.RootProvider value={dialog}>
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
{dialog.open ? "Close" : "Open"} Dialog
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.RootProvider>
)
}
Context
Use the DialogContext
component to access the dialog state and methods from
outside the dialog.
"use client"
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Dialog.Root>
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Context>
{(store) => (
<Dialog.Body pt="6" spaceY="3">
<p>Dialog is open: {store.open ? "true" : "false"}</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
do eiusmod tempor incididunt ut labore et dolore magna
aliqua.
</p>
<button onClick={() => store.setOpen(false)}>Close</button>
</Dialog.Body>
)}
</Dialog.Context>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Initial Focus
Use the initialFocusEl
prop to set the initial focus of the dialog component.
"use client"
import { Button, Dialog, Field, Input, Portal, Stack } from "@chakra-ui/react"
import { useRef } from "react"
const Demo = () => {
const ref = useRef<HTMLInputElement>(null)
return (
<Dialog.Root initialFocusEl={() => ref.current}>
<Dialog.Trigger asChild>
<Button variant="outline">Open</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Header</Dialog.Title>
</Dialog.Header>
<Dialog.Body pb="4">
<Stack gap="4">
<Field.Root>
<Field.Label>First Name</Field.Label>
<Input placeholder="First Name" />
</Field.Root>
<Field.Root>
<Field.Label>Last Name</Field.Label>
<Input ref={ref} placeholder="Focus First" />
</Field.Root>
</Stack>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Inside Scroll
Use the scrollBehavior=inside
prop to change the scroll behavior of the dialog
when its content overflows.
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
import Lorem from "react-lorem-ipsum"
const Demo = () => {
return (
<Dialog.Root scrollBehavior="inside" size="sm">
<Dialog.Trigger asChild>
<Button variant="outline">Inside Scroll</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>With Inside Scroll</Dialog.Title>
</Dialog.Header>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
<Dialog.Body>
<Lorem p={8} />
</Dialog.Body>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Outside Scroll
Use the scrollBehavior=outside
prop to change the scroll behavior of the
dialog when its content overflows.
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
import Lorem from "react-lorem-ipsum"
const Demo = () => {
return (
<Dialog.Root size="sm" scrollBehavior="outside">
<Dialog.Trigger asChild>
<Button variant="outline">Outside Scroll</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>With Outside Scroll</Dialog.Title>
</Dialog.Header>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
<Dialog.Body>
<Lorem p={8} />
</Dialog.Body>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Motion Preset
Use the motionPreset
prop to change the animation of the dialog component.
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Dialog.Root motionPreset="slide-in-bottom">
<Dialog.Trigger asChild>
<Button variant="outline">Slide in Bottom</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button>Save</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Alert Dialog
Set the role: "alertdialog"
prop to change the dialog component to an alert
dialog.
import { Button, CloseButton, Dialog, Portal } from "@chakra-ui/react"
const Demo = () => {
return (
<Dialog.Root role="alertdialog">
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Are you sure?</Dialog.Title>
</Dialog.Header>
<Dialog.Body>
<p>
This action cannot be undone. This will permanently delete your
account and remove your data from our systems.
</p>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="outline">Cancel</Button>
</Dialog.ActionTrigger>
<Button colorPalette="red">Delete</Button>
</Dialog.Footer>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
Close Button Outside
Here's an example of how to customize the Dialog.CloseTrigger
component to
position the close button outside the dialog component.
import {
AspectRatio,
Button,
CloseButton,
Dialog,
Portal,
} from "@chakra-ui/react"
const Demo = () => {
return (
<Dialog.Root placement="center">
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Body pt="4">
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.Description mb="4">
This is a dialog with some content and a video.
</Dialog.Description>
<AspectRatio ratio={4 / 3} rounded="lg" overflow="hidden">
<iframe
title="naruto"
src="https://www.youtube.com/embed/QhBnZ6NPOY0"
allowFullScreen
/>
</AspectRatio>
</Dialog.Body>
<Dialog.CloseTrigger top="0" insetEnd="-12" asChild>
<CloseButton bg="bg" size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
)
}
DataList
Here's an example of how to compose the dialog component with the DataList
component.
import {
Avatar,
Badge,
Button,
CloseButton,
DataList,
Dialog,
HStack,
Portal,
Textarea,
VStack,
} from "@chakra-ui/react"
const Demo = () => {
return (
<VStack alignItems="start">
<Dialog.Root>
<Dialog.Trigger asChild>
<Button variant="outline">Open Dialog</Button>
</Dialog.Trigger>
<Portal>
<Dialog.Backdrop />
<Dialog.Positioner>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Prepare Chakra V3</Dialog.Title>
</Dialog.Header>
<Dialog.Body pb="8">
<DataList.Root orientation="horizontal">
<DataList.Item>
<DataList.ItemLabel>Status</DataList.ItemLabel>
<DataList.ItemValue>
<Badge colorPalette="green">Completed</Badge>
</DataList.ItemValue>
</DataList.Item>
<DataList.Item>
<DataList.ItemLabel>Assigned to</DataList.ItemLabel>
<DataList.ItemValue>
<HStack>
<Avatar.Root size="xs">
<Avatar.Image src="https://bit.ly/sage-adebayo" />
<Avatar.Fallback name="Segun Adebayo" />
</Avatar.Root>
Segun Adebayo
</HStack>
</DataList.ItemValue>
</DataList.Item>
<DataList.Item>
<DataList.ItemLabel>Due date</DataList.ItemLabel>
<DataList.ItemValue>12th August 2024</DataList.ItemValue>
</DataList.Item>
</DataList.Root>
<Textarea placeholder="Add a note" mt="8" />
</Dialog.Body>
<Dialog.CloseTrigger asChild>
<CloseButton size="sm" />
</Dialog.CloseTrigger>
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
</VStack>
)
}
Props
Root
Prop | Default | Type |
---|---|---|
closeOnEscape | true | boolean Whether to close the dialog when the escape key is pressed |
closeOnInteractOutside | true | boolean Whether to close the dialog when the outside is clicked |
lazyMount | false | boolean Whether to enable lazy mounting |
modal | true | boolean Whether to prevent pointer interaction outside the element and hide all content below it |
preventScroll | true | boolean Whether to prevent scrolling behind the dialog when it's opened |
role | '\'dialog\'' | 'dialog' | 'alertdialog' The dialog's role |
trapFocus | true | boolean Whether to trap focus inside the dialog when it's opened |
unmountOnExit | false | boolean Whether to unmount on exit. |
colorPalette | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' The color palette of the component |
placement | 'top' | 'center' | 'top' | 'bottom' The placement of the component |
scrollBehavior | 'outside' | 'inside' | 'outside' The scrollBehavior of the component |
size | 'md' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'cover' | 'full' The size of the component |
motionPreset | 'scale' | 'scale' | 'slide-in-bottom' | 'slide-in-top' | 'slide-in-left' | 'slide-in-right' | 'none' The motionPreset of the component |
aria-label | string Human readable label for the dialog, in event the dialog title is not rendered | |
defaultOpen | boolean The initial open state of the dialog when it is first rendered. Use when you do not need to control its open state. | |
finalFocusEl | () => HTMLElement | null Element to receive focus when the dialog is closed | |
id | string The unique identifier of the machine. | |
ids | Partial<{
trigger: string
positioner: string
backdrop: string
content: string
closeTrigger: string
title: string
description: string
}> The ids of the elements in the dialog. Useful for composition. | |
immediate | boolean Whether to synchronize the present change immediately or defer it to the next frame | |
initialFocusEl | () => HTMLElement | null Element to receive focus when the dialog is opened | |
onEscapeKeyDown | (event: KeyboardEvent) => void Function called when the escape key is pressed | |
onExitComplete | () => void Function called when the animation ends in the closed state | |
onFocusOutside | (event: FocusOutsideEvent) => void Function called when the focus is moved outside the component | |
onInteractOutside | (event: InteractOutsideEvent) => void Function called when an interaction happens outside the component | |
onOpenChange | (details: OpenChangeDetails) => void Callback to be invoked when the dialog is opened or closed | |
onPointerDownOutside | (event: PointerDownOutsideEvent) => void Function called when the pointer is pressed down outside the component | |
open | boolean Whether the dialog is open | |
persistentElements | (() => Element | null)[] Returns the persistent elements that: - should not have pointer-events disabled - should not trigger the dismiss event | |
present | boolean Whether the node is present (controlled by the user) | |
restoreFocus | boolean Whether to restore focus to the element that had focus before the dialog was opened | |
as | React.ElementType The underlying element to render. | |
asChild | boolean Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
unstyled | boolean Whether to remove the component's style. |