import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
const Demo = () => {
return (
<DialogRoot>
<DialogTrigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
</DialogHeader>
<DialogBody>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</DialogBody>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</DialogFooter>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
)
}
Setup
If you don't already have the snippet, run the following command to add the
dialog
snippet
chakra snippet add dialog
The snippet includes a closed component composition for the Dialog
component.
Usage
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
<DialogRoot>
<DialogBackdrop />
<DialogTrigger />
<DialogContent>
<DialogCloseTrigger />
<DialogHeader>
<DialogTitle />
</DialogHeader>
<DialogBody />
<DialogFooter />
</DialogContent>
</DialogRoot>
Examples
Sizes
Use the size
prop to change the size of the dialog component.
import { For, HStack } from "@chakra-ui/react"
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
const Demo = () => {
return (
<HStack>
<For each={["xs", "sm", "md", "lg"]}>
{(size) => (
<DialogRoot key={size} size={size}>
<DialogTrigger asChild>
<Button variant="outline" size={size}>
Open ({size})
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
</DialogHeader>
<DialogBody>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</DialogBody>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</DialogFooter>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
)}
</For>
</HStack>
)
}
Centered
Use the centered
prop to center the dialog component.
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
const Demo = () => {
return (
<DialogRoot centered>
<DialogTrigger asChild>
<Button variant="outline">Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
</DialogHeader>
<DialogBody>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</DialogBody>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</DialogFooter>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
)
}
Controlled
Use the open
and onOpenChange
prop to control the visibility of the dialog
component.
"use client"
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { useState } from "react"
import Lorem from "react-lorem-ipsum"
const Demo = () => {
const [open, setOpen] = useState(false)
return (
<DialogRoot lazyMount open={open} onOpenChange={(e) => setOpen(e.open)}>
<DialogTrigger asChild>
<Button variant="outline">Open</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
</DialogHeader>
<DialogBody>
<Lorem p={2} />
</DialogBody>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</DialogFooter>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
)
}
Initial Focus
Use the initialFocusEl
prop to set the initial focus of the dialog component.
"use client"
import { Input, Stack } from "@chakra-ui/react"
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Field } from "@/components/ui/field"
import { useRef } from "react"
const Demo = () => {
const ref = useRef<HTMLInputElement>(null)
return (
<DialogRoot initialFocusEl={() => ref.current}>
<DialogTrigger asChild>
<Button variant="outline">Open</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Header</DialogTitle>
</DialogHeader>
<DialogBody pb="4">
<Stack gap="4">
<Field label="First Name">
<Input placeholder="First Name" />
</Field>
<Field label="Last Name">
<Input ref={ref} placeholder="Focus First" />
</Field>
</Stack>
</DialogBody>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</DialogFooter>
</DialogContent>
</DialogRoot>
)
}
Inside Scroll
Use the scrollBehavior=inside
prop to change the scroll behavior of the dialog
when its content overflows.
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogHeader,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog"
import Lorem from "react-lorem-ipsum"
const Demo = () => {
return (
<DialogRoot scrollBehavior="inside" size="sm">
<DialogTrigger asChild>
<Button variant="outline">Inside Scroll</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>With Inside Scroll</DialogHeader>
<DialogCloseTrigger />
<DialogBody>
<Lorem p={8} />
</DialogBody>
</DialogContent>
</DialogRoot>
)
}
Outside Scroll
Use the scrollBehavior=outside
prop to change the scroll behavior of the
dialog when its content overflows.
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogHeader,
DialogRoot,
DialogTrigger,
} from "@/components/ui/dialog"
import Lorem from "react-lorem-ipsum"
const Demo = () => {
return (
<DialogRoot size="sm">
<DialogTrigger asChild>
<Button variant="outline">Outside Scroll</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>With Outside Scroll</DialogHeader>
<DialogCloseTrigger />
<DialogBody>
<Lorem p={8} />
</DialogBody>
</DialogContent>
</DialogRoot>
)
}
Motion Preset
Use the motionPreset
prop to change the animation of the dialog component.
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
const Demo = () => {
return (
<DialogRoot motionPreset="slide-in-bottom">
<DialogTrigger asChild>
<Button variant="outline">Slide in Bottom</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
</DialogHeader>
<DialogBody>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</DialogBody>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</DialogFooter>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
)
}
Alert Dialog
Set the role: "alertdialog"
prop to change the dialog component to an alert
dialog.
import { Button } from "@/components/ui/button"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogFooter,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
const Demo = () => {
return (
<DialogRoot role="alertdialog">
<DialogTrigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
</DialogHeader>
<DialogBody>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua.
</p>
</DialogBody>
<DialogFooter>
<Button variant="outline">Cancel</Button>
<Button>Save</Button>
</DialogFooter>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
)
}
With DataList
Here's an example of how to compose the dialog component with the DataList
component.
import { Badge, HStack, Textarea, VStack } from "@chakra-ui/react"
import { Avatar } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import { DataListItem, DataListRoot } from "@/components/ui/data-list"
import {
DialogBody,
DialogCloseTrigger,
DialogContent,
DialogHeader,
DialogRoot,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
const Demo = () => {
return (
<VStack alignItems="start">
<DialogRoot>
<DialogTrigger asChild>
<Button variant="outline">Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Prepare Chakra V3</DialogTitle>
</DialogHeader>
<DialogBody pb="8">
<DataListRoot orientation="horizontal">
<DataListItem
label="Status"
value={<Badge colorPalette="green">Completed</Badge>}
/>
<DataListItem
label="Assigned to"
value={
<HStack>
<Avatar
name="Segun Adebayo"
src="https://bit.ly/sage-adebayo"
/>
Segun Adebayo
</HStack>
}
/>
<DataListItem label="Due date" value="12th August 2024" />
</DataListRoot>
<Textarea placeholder="Add a note" mt="8" />
</DialogBody>
<DialogCloseTrigger />
</DialogContent>
</DialogRoot>
</VStack>
)
}