Skip to content

Dialog

A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.

Code
import {
Button,
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
Field,
FieldGroup,
Input,
Label,
} from "@falcon/ui-kit";
export function Example() {
return (
<Dialog>
<form>
<DialogTrigger render={<Button variant="outline" />}>
Open Dialog
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you&apos;re
done.
</DialogDescription>
</DialogHeader>
<FieldGroup>
<Field>
<Label htmlFor="name-1">Name</Label>
<Input id="name-1" name="name" defaultValue="Maria Larsen" />
</Field>
<Field>
<Label htmlFor="username-1">Username</Label>
<Input id="username-1" name="username" defaultValue="@mlarsen" />
</Field>
</FieldGroup>
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>
Cancel
</DialogClose>
<Button type="submit">Save changes</Button>
</DialogFooter>
</DialogContent>
</form>
</Dialog>
);
}

Use the following composition to build a Dialog:

Dialog
├── DialogTrigger
└── DialogContent
├── DialogHeader
│ ├── DialogTitle
│ └── DialogDescription
└── DialogFooter

Replace the default close control with your own button.

Code
import {
Button,
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
Input,
Label,
} from "@falcon/ui-kit";
export function Example() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>Share</DialogTrigger>
<DialogContent className="tw:sm:max-w-md">
<DialogHeader>
<DialogTitle>Share link</DialogTitle>
<DialogDescription>
Anyone who has this link will be able to view this.
</DialogDescription>
</DialogHeader>
<div className="tw:flex tw:items-center tw:gap-2">
<div className="tw:grid tw:flex-1 tw:gap-2">
<Label htmlFor="link" className="tw:sr-only">
Link
</Label>
<Input
id="link"
defaultValue="https://portal.example.com/quotes/1042"
readOnly
/>
</div>
</div>
<DialogFooter className="tw:sm:justify-start">
<DialogClose render={<Button type="button" />}>Close</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

Use showCloseButton={false} to hide the close button.

Code
import {
Button,
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@falcon/ui-kit";
export function Example() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
No Close Button
</DialogTrigger>
<DialogContent showCloseButton={false}>
<DialogHeader>
<DialogTitle>No Close Button</DialogTitle>
<DialogDescription>
This dialog doesn&apos;t have a close button in the top-right
corner.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
);
}

Keep actions visible while the content scrolls.

Code
import {
Button,
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@falcon/ui-kit";
export function Example() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Sticky Footer
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Sticky Footer</DialogTitle>
<DialogDescription>
This dialog has a sticky footer that stays visible while the content
scrolls.
</DialogDescription>
</DialogHeader>
<div className="tw:-mx-4 tw:max-h-[50vh] tw:overflow-y-auto tw:px-4">
{Array.from({ length: 10 }).map((_, index) => (
<p key={index} className="tw:mb-4 tw:leading-normal">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
))}
</div>
<DialogFooter>
<DialogClose render={<Button variant="outline" />}>Close</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}

Long content can scroll while the header stays in view.

Code
import {
Button,
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@falcon/ui-kit";
export function Example() {
return (
<Dialog>
<DialogTrigger render={<Button variant="outline" />}>
Scrollable Content
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Scrollable Content</DialogTitle>
<DialogDescription>
This is a dialog with scrollable content.
</DialogDescription>
</DialogHeader>
<div className="tw:-mx-4 tw:max-h-[50vh] tw:overflow-y-auto tw:px-4">
{Array.from({ length: 10 }).map((_, index) => (
<p key={index} className="tw:mb-4 tw:leading-normal">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint occaecat cupidatat non proident,
sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
))}
</div>
</DialogContent>
</Dialog>
);
}

Groups a dialog’s parts. Open it with a nested DialogTrigger or the open/defaultOpen props; there is no detached-trigger or imperative API.

children?: React.ReactNode

The content of the dialog.

defaultOpen?: boolean

Whether the dialog is initially open. To render a controlled dialog, use the open prop instead.

defaultTriggerId?: string | null

ID of the trigger associated with an initially open dialog.

disablePointerDismissal?: boolean

Whether to prevent the dialog from closing on outside presses.

modal?: boolean | "trap-focus"

Determines if the dialog enters a modal state when open. true traps focus, locks page scroll, and disables pointer interactions outside the dialog. false allows interaction with the rest of the document. 'trap-focus' traps focus without locking scroll or disabling outside pointer interactions.

onOpenChange?: ((open: boolean, eventDetails: DialogPrimitive.Root.ChangeEventDetails) => void)

Event handler called when the dialog is opened or closed.

onOpenChangeComplete?: ((open: boolean) => void)

Event handler called after animations complete when the dialog is opened or closed.

open?: boolean

Whether the dialog is currently open.

triggerId?: string | null

ID of the trigger associated with a controlled dialog.

Closes the dialog. Renders a <button> element and accepts standard <button> props. Use render to replace the element.

className?: string | ((state: DialogCloseState) => string | undefined)

CSS class applied to the element, or a function that returns a class based on its state.

nativeButton?: boolean

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogCloseState>

Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogCloseState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.

Includes the portal and backdrop. Renders a <div> element and accepts standard <div> props. Use render to replace the element. Use it with a DialogTitle and DialogDescription so the dialog has an accessible name and description.

className?: string

CSS class applied to the dialog.

finalFocus?: boolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void)

Determines the element to focus when the dialog is closed.

initialFocus?: boolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void)

Determines the element to focus when the dialog is opened.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogPopupState>

Allows you to replace the dialog’s HTML element with a different tag, or compose it with another component. Accepts a React element or a function that returns the element to render.

showCloseButton?: boolean = true

Whether to render the default close button.

style?: React.CSSProperties | ((state: DialogPopupState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the dialog’s state.

Provides the dialog’s accessible description. Renders a <p> element and accepts standard <p> props. Use render to replace the element.

className?: string

CSS class applied to the element.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogDescriptionState>

Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogDescriptionState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.

Contains dialog actions. Renders a <div> element and accepts standard <div> props.

showCloseButton?: boolean

Whether to render a default close button.

Groups DialogTitle and DialogDescription. Renders a <div> element and accepts standard <div> props.

Provides the dialog’s accessible name. Renders an <h2> element and accepts standard <h2> props. Use render to replace the element.

className?: string

CSS class applied to the element.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTitleState>

Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogTitleState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.

Opens the associated dialog. Renders a <button> element and accepts standard <button> props. Use render to replace the element.

className?: string | ((state: DialogTriggerState) => string | undefined)

CSS class applied to the element, or a function that returns a class based on its state.

id?: string

ID of the trigger. In addition to being forwarded to the rendered element, it identifies the active trigger in controlled mode with triggerId.

nativeButton?: boolean

Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button.

render?: React.ReactElement<any, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, DialogTriggerState>

Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a React element or a function that returns the element to render.

style?: React.CSSProperties | ((state: DialogTriggerState) => React.CSSProperties | undefined)

Style applied to the element, or a function that returns a style object based on the component’s state.