Dialog

A modal dialog component for displaying content in an overlay.

import {
  DialogRoot,
  DialogTrigger,
  DialogPortal,
  DialogOverlay,
  DialogPopup,
  DialogHeader,
  DialogFooter,
  DialogTitle,
  DialogDescription,
  DialogClose,
} from "@/components/ui/dialog/dialog";
import { Button } from "@/components/ui/button/button";
import { Input } from "@/components/ui/input/input";
import styles from "./dialog-demo.module.css";

export default function DialogDemo() {
  return (
    <DialogRoot>
      <DialogTrigger render={<Button>Open Dialog</Button>} />
      <DialogPortal>
        <DialogOverlay />
        <DialogPopup className={styles.popup}>
          <DialogHeader>
            <DialogTitle>Edit Profile</DialogTitle>
            <DialogDescription>Make changes to your profile here.</DialogDescription>
          </DialogHeader>
          <div className={styles.form}>
            <div className={styles.fieldGroup}>
              <label className={styles.label}>Name</label>
              <Input defaultValue="John Doe" />
            </div>
            <div className={styles.fieldGroup}>
              <label className={styles.label}>Email</label>
              <Input type="email" defaultValue="john@example.com" />
            </div>
          </div>
          <DialogFooter>
            <DialogClose render={<Button variant="secondary">Cancel</Button>} />
            <Button>Save Changes</Button>
          </DialogFooter>
        </DialogPopup>
      </DialogPortal>
    </DialogRoot>
  );
}

Installation

npx shadcn@latest add https://roiui.com/r/dialog.json

Anatomy

anatomy
import {
DialogRoot,
DialogTrigger,
DialogContent,
DialogHeader,
DialogFooter,
DialogTitle,
DialogDescription,
DialogClose,
} from '../ui/dialog'

<DialogRoot>
  <DialogTrigger />
  <DialogContent>
      <DialogHeader>
          <DialogTitle />
          <DialogDescription />
      </DialogHeader>
      <DialogFooter>
          <DialogClose />
      </DialogFooter>
  </DialogContent>
</DialogRoot>

Examples

With Motion

"use client";

import { Dialog } from "@base-ui-components/react/dialog";
import { motion, AnimatePresence } from "motion/react";
import { useState } from "react";
import { Button } from "@/components/ui/button/button";
import styles from "./dialog-motion.module.css";

const overlayVariants = {
  hidden: { opacity: 0 },
  visible: { opacity: 1 },
};

const overlayTransition = {
  duration: 0.2,
};

const popupVariants = {
  hidden: {
    opacity: 0,
    scale: 0.8,
  },
  visible: {
    opacity: 1,
    scale: 1,
  },
};

const popupTransition = {
  duration: 0.2,
  layout: { duration: 0.2 },
};

const buttonTransition = {
  duration: 0.2,
};

export default function DialogFramerMotion() {
  const [open, setOpen] = useState(false);

  return (
    <div>
      <Dialog.Root open={open} onOpenChange={setOpen} key="root">
        <motion.div layoutId="container">
          <motion.div layoutId="button">
            <Dialog.Trigger render={<Button />}>Toggle Dialog</Dialog.Trigger>
          </motion.div>
        </motion.div>

        <Dialog.Backdrop
          render={
            <AnimatePresence>
              {open && (
                <motion.div
                  key="overlay"
                  className={styles.overlay}
                  variants={overlayVariants}
                  initial="hidden"
                  animate="visible"
                  exit="hidden"
                  transition={overlayTransition}
                />
              )}
            </AnimatePresence>
          }
        />
        <Dialog.Portal>
          <AnimatePresence>
            {open && (
              <Dialog.Popup
                key="modal"
                render={
                  <motion.div
                    className={styles.popup}
                    layoutId="container"
                    variants={popupVariants}
                    initial="hidden"
                    animate="visible"
                    exit="hidden"
                    transition={popupTransition}
                  />
                }
              >
                <Dialog.Title className={styles.title}>What is a brook?</Dialog.Title>
                <Dialog.Description>
                  A small, natural stream of fresh water, often winding gently through forests, meadows, or valleys.
                </Dialog.Description>
                <div className={styles.actions}>
                  <Dialog.Close render={<Button variant="secondary">Close</Button>}>Close</Dialog.Close>
                  <motion.div layoutId="button" transition={buttonTransition}>
                    <Button>Toggle Dialog</Button>
                  </motion.div>
                </div>
              </Dialog.Popup>
            )}
          </AnimatePresence>
        </Dialog.Portal>
      </Dialog.Root>
    </div>
  );
}