'use client'
import { Button, Dialog } from '@saas-ui/react'
export const DialogBasic = () => {
return (
<Dialog.Root>
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.CloseButton />
</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="ghost">Cancel</Button>
</Dialog.ActionTrigger>
<Button variant="glass" colorPalette="accent">
Save
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
)
}
import { Dialog } from '@saas-ui/react/dialog'
<Dialog.Root>
<Dialog.Backdrop />
<Dialog.Trigger />
<Dialog.Content>
<Dialog.Header>
<Dialog.Title />
<Dialog.CloseButton />
</Dialog.Header>
<Dialog.Body />
<Dialog.Footer>
<Dialog.CloseTrigger asChild>
<Button>Close</Button>
</Dialog.CloseTrigger>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
Use the size
prop to change the size of the dialog component.
'use client'
import { For, HStack } from '@chakra-ui/react'
import { Button, Dialog } from '@saas-ui/react'
export const DialogWithSizes = () => {
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>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.CloseButton />
</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="ghost">Cancel</Button>
</Dialog.ActionTrigger>
<Button variant="glass" colorPalette="accent">
Save
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
)}
</For>
</HStack>
)
}
Use the size="cover"
prop to make the dialog component cover the entire screen
while revealing a small portion of the page behind.
'use client'
import { Button, Dialog } from '@saas-ui/react'
export const DialogWithCover = () => {
return (
<Dialog.Root size="cover" placement="center" motionPreset="slide-in-bottom">
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.CloseButton />
</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.Root>
)
}
Use the open
and onOpenChange
prop to control the visibility of the dialog
component.
'use client'
import { useState } from 'react'
import { Button, Dialog } from '@saas-ui/react'
import Lorem from 'react-lorem-ipsum'
export const DialogControlled = () => {
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>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.CloseButton />
</Dialog.Header>
<Dialog.Body>
<Lorem p={2} />
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="ghost">Cancel</Button>
</Dialog.ActionTrigger>
<Button variant="glass" colorPalette="accent">
Save
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
)
}
Use the initialFocusEl
prop to set the initial focus of the dialog component.
'use client'
import { useRef } from 'react'
import { Input, Stack } from '@chakra-ui/react'
import { Button, Dialog } from '@saas-ui/react'
export const DialogWithInitialFocus = () => {
const ref = useRef<HTMLInputElement>(null)
return (
<Dialog.Root initialFocusEl={() => ref.current}>
<Dialog.Trigger asChild>
<Button variant="outline">Open</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Header</Dialog.Title>
</Dialog.Header>
<Dialog.Body pb="4">
<Stack gap="4">
<Input placeholder="First Name" />
<Input placeholder="Last Name" />
<Input ref={ref} placeholder="Focus First" />
</Stack>
</Dialog.Body>
<Dialog.Footer>
<Dialog.ActionTrigger asChild>
<Button variant="ghost">Cancel</Button>
</Dialog.ActionTrigger>
<Button variant="glass" colorPalette="accent">
Save
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
)
}
Use the scrollBehavior=inside
prop to change the scroll behavior of the dialog
when its content overflows.
'use client'
import { Button, Dialog } from '@saas-ui/react'
import Lorem from 'react-lorem-ipsum'
export const DialogWithInsideScroll = () => {
return (
<Dialog.Root scrollBehavior="inside" size="sm">
<Dialog.Trigger asChild>
<Button variant="outline">Inside Scroll</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>With Inside Scroll</Dialog.Title>
<Dialog.CloseButton />
</Dialog.Header>
<Dialog.Body>
<Lorem p={8} />
</Dialog.Body>
</Dialog.Content>
</Dialog.Root>
)
}
Use the scrollBehavior=outside
prop to change the scroll behavior of the
dialog when its content overflows.
'use client'
import { Button, Dialog } from '@saas-ui/react'
import Lorem from 'react-lorem-ipsum'
export const DialogWithOutsideScroll = () => {
return (
<Dialog.Root size="sm" scrollBehavior="outside">
<Dialog.Trigger asChild>
<Button variant="outline">Outside Scroll</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>With Outside Scroll</Dialog.Title>
<Dialog.CloseButton />
</Dialog.Header>
<Dialog.Body>
<Lorem p={8} />
</Dialog.Body>
</Dialog.Content>
</Dialog.Root>
)
}
Use the motionPreset
prop to change the animation of the dialog component.
'use client'
import { Button, Dialog } from '@saas-ui/react'
export const DialogWithMotionPreset = () => {
return (
<Dialog.Root motionPreset="slide-in-bottom">
<Dialog.Trigger asChild>
<Button variant="outline">Slide in Bottom</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.CloseButton />
</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="ghost">Cancel</Button>
</Dialog.ActionTrigger>
<Button variant="glass" colorPalette="accent">
Save
</Button>
</Dialog.Footer>
</Dialog.Content>
</Dialog.Root>
)
}
Set the role: "alertdialog"
prop to change the dialog component to an alert
dialog.
'use client'
import { Button, Dialog } from '@saas-ui/react'
export const DialogWithRole = () => {
return (
<Dialog.Root role="alertdialog">
<Dialog.Trigger asChild>
<Button variant="outline" size="sm">
Open Dialog
</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Are you sure?</Dialog.Title>
<Dialog.CloseButton />
</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="ghost">Cancel</Button>
</Dialog.ActionTrigger>
<Button variant="glass" colorPalette="red">
Delete
</Button>
</Dialog.Footer>
<Dialog.CloseTrigger />
</Dialog.Content>
</Dialog.Root>
)
}
Here's an example of how to compose the dialog component with the DataList
component.
'use client'
import { HStack, Textarea, VStack } from '@chakra-ui/react'
import { Avatar, Badge, Button, DataList, Dialog } from '@saas-ui/react'
export const DialogWithDatalist = () => {
return (
<VStack alignItems="start">
<Dialog.Root>
<Dialog.Trigger asChild>
<Button variant="outline">Open Dialog</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Header>
<Dialog.Title>Prepare Chakra V3</Dialog.Title>
<Dialog.CloseButton />
</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
size="xs"
name="Eelco Wiersma"
src="https://eelco.dev"
/>
Eelco Wiersma
</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.Content>
</Dialog.Root>
</VStack>
)
}
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' | 'accent' The color palette of the component |
scrollBehavior | 'outside' | 'inside' | 'outside' The scrollBehavior of the component |
size | 'md' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '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 | |
centered | 'true' | 'false' The centered of the component | |
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. |