Components

Base Components

Dialog

A window over the page for critical actions or information.

Example

Installation

Install the following dependencies:

npm install radix-uinpm install lucide-react

Create a dialog.tsx file and paste the following code into it.

"use client";import * as React from "react";import { XIcon } from "lucide-react";import { Dialog as DialogPrimitive } from "radix-ui";import { cn } from "@/lib/utils";import { Button } from "@/components/ui/button";function Dialog({  ...props}: React.ComponentProps<typeof DialogPrimitive.Root>) {  return <DialogPrimitive.Root data-slot="dialog" {...props} />;}function DialogTrigger({  ...props}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {  return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;}function DialogPortal({  ...props}: React.ComponentProps<typeof DialogPrimitive.Portal>) {  return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;}function DialogClose({  ...props}: React.ComponentProps<typeof DialogPrimitive.Close>) {  return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;}function DialogOverlay({  className,  ...props}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {  return (    <DialogPrimitive.Overlay      data-slot="dialog-overlay"      className={cn(        "fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",        className,      )}      {...props}    />  );}export type DialogContentProps = React.ComponentProps<  typeof DialogPrimitive.Content> & {  showCloseButton?: boolean;  /** When `false`, hides the corner close control (same as `showCloseButton={false}`). */  showClose?: boolean;  dir?: React.HTMLAttributes<HTMLDivElement>["dir"];};function DialogContent({  className,  children,  showCloseButton = true,  showClose,  ...props}: DialogContentProps) {  const shouldShowCloseButton =    showCloseButton !== false && showClose !== false;  return (    <DialogPortal>      <DialogOverlay />      <DialogPrimitive.Content        data-slot="dialog-content"        className={cn(          "fixed top-1/2 left-1/2 z-50 flex w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 flex-col gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",          className,        )}        {...props}      >        {children}        {shouldShowCloseButton && (          <DialogPrimitive.Close data-slot="dialog-close" asChild>            <Button              variant="ghost"              className="absolute top-2 end-2"              size="sm"            >              <XIcon />              <span className="sr-only">Close</span>            </Button>          </DialogPrimitive.Close>        )}      </DialogPrimitive.Content>    </DialogPortal>  );}function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {  return (    <div      data-slot="dialog-header"      className={cn("flex flex-col gap-2", className)}      {...props}    />  );}function DialogFooter({  className,  showCloseButton = false,  children,  ...props}: React.ComponentProps<"div"> & {  showCloseButton?: boolean;}) {  return (    <div      data-slot="dialog-footer"      className={cn(        "flex w-full flex-col gap-2 border-t border-border pt-4 sm:flex-row sm:justify-end sm:gap-2",        className,      )}      {...props}    >      {children}      {showCloseButton && (        <DialogPrimitive.Close asChild>          <Button variant="primary">Close</Button>        </DialogPrimitive.Close>      )}    </div>  );}function DialogTitle({  className,  ...props}: React.ComponentProps<typeof DialogPrimitive.Title>) {  return (    <DialogPrimitive.Title      data-slot="dialog-title"      className={cn(        "cn-font-heading text-base leading-none font-medium",        className,      )}      {...props}    />  );}function DialogDescription({  className,  ...props}: React.ComponentProps<typeof DialogPrimitive.Description>) {  return (    <DialogPrimitive.Description      data-slot="dialog-description"      className={cn(        "text-sm 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,};

Check the import paths to ensure they match your project setup.

Usage

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";

<Dialog>
  <DialogTrigger asChild>
    <Button>Open</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Are you absolutely sure?</DialogTitle>
      <DialogDescription>
        This action cannot be undone. This will permanently delete your account
        and remove your data from our servers.
      </DialogDescription>
    </DialogHeader>
  </DialogContent>
</Dialog>
DialogContent shows a corner close control by default. Pass showCloseButton={false} (or showClose={false}) to hide it and use DialogClose with your own button instead.

Examples

Basic

A minimal dialog with a title, description, and primary action.

Custom close button

Replace the default corner close control with your own DialogClose (for example a Done action in the header). Set showCloseButton={false} on DialogContent so the built-in control is not rendered.

No close button

Use showCloseButton={false} when you do not want an “X” in the corner—often paired with explicit Cancel / Continue actions in the footer.
Keep header and footer fixed while the middle section scrolls. Use a column flex layout on DialogContent, min-h-0 flex-1 overflow-y-auto on the body, and put actions in DialogFooter.

Scrollable content

Long content can scroll while the title and description stay at the top. Constrain DialogContent height and make only the main body overflow-y-auto.

RTL

Right-to-left layouts: wrap the trigger and dialog in a container with dir="rtl" (or set direction on the document). Mirror spacing in the footer if your design requires it.

API Reference

BlakeUI Dialog wraps Radix Dialog primitives: Dialog, DialogTrigger, DialogContent (supports showCloseButton and showClose to toggle the default corner close button), DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose, DialogPortal, and DialogOverlay. See the Radix Dialog documentation for focus management and accessibility.

On this page