Devie UI

The AlertDialog component extends the Base UI Alert Dialog with additional structural sub-components: AlertDialog.Header, AlertDialog.Body, and AlertDialog.Footer. While this adds to an already comprehensive component, these additions provide consistent layout patterns and better support for richer use cases beyond simple confirmation messages.

Installation

Here is the component implementation code that you can copy to your project:

"use client";
 
import { AlertDialog as BaseAlertDialog } from "@base-ui-components/react/alert-dialog";
import clsx from "clsx";
import styles from "./AlertDialog.module.scss";
 
const Root = BaseAlertDialog.Root;
 
interface TriggerProps extends BaseAlertDialog.Trigger.Props {
  className?: string;
}
 
function Trigger({ className, ...props }: TriggerProps) {
  return (
    <BaseAlertDialog.Trigger
      className={clsx(styles.trigger, className)}
      {...props}
    />
  );
}
 
const Portal = BaseAlertDialog.Portal;
 
interface CloseProps extends BaseAlertDialog.Close.Props {
  className?: string;
}
 
function Close({ className, ...props }: CloseProps) {
  return (
    <BaseAlertDialog.Close
      className={clsx(styles.close, className)}
      {...props}
    />
  );
}
 
interface BackdropProps extends BaseAlertDialog.Backdrop.Props {
  className?: string;
}
 
function Backdrop({ className, ...props }: BackdropProps) {
  return (
    <BaseAlertDialog.Backdrop
      className={clsx(styles.backdrop, className)}
      {...props}
    />
  );
}
 
interface PopupProps extends BaseAlertDialog.Popup.Props {
  className?: string;
}
 
function Popup({ className, ...props }: PopupProps) {
  return (
    <BaseAlertDialog.Popup
      className={clsx(styles.popup, className)}
      {...props}
    />
  );
}
 
interface TitleProps extends BaseAlertDialog.Title.Props {
  className?: string;
}
 
function Title({ className, ...props }: TitleProps) {
  return (
    <BaseAlertDialog.Title
      className={clsx(styles.title, className)}
      render={({ children }) => (
        <h3 className={clsx(styles.title, className)} {...props}>
          {children}
        </h3>
      )}
      {...props}
    />
  );
}
 
interface DescriptionProps extends BaseAlertDialog.Description.Props {
  className?: string;
}
 
function Description({ className, ...props }: DescriptionProps) {
  return (
    <BaseAlertDialog.Description
      className={clsx(styles.description, className)}
      {...props}
    />
  );
}
 
interface HeaderProps extends React.HTMLAttributes<HTMLDivElement> {
  className?: string;
}
 
function Header({ className, ...props }: HeaderProps) {
  return <div className={clsx(styles.header, className)} {...props} />;
}
 
interface FooterProps extends React.HTMLAttributes<HTMLDivElement> {
  className?: string;
}
 
function Footer({ className, ...props }: FooterProps) {
  return <div className={clsx(styles.footer, className)} {...props} />;
}
 
interface BodyProps extends React.HTMLAttributes<HTMLDivElement> {
  className?: string;
}
 
function Body({ className, ...props }: BodyProps) {
  return <div className={clsx(styles.body, className)} {...props} />;
}
 
const AlertDialog = {
  Root,
  Trigger,
  Portal,
  Close,
  Backdrop,
  Popup,
  Header,
  Footer,
  Title,
  Description,
  Body,
};
 
export type AlertDialogProps = React.ComponentProps<
  typeof BaseAlertDialog.Root
>;
 
export default AlertDialog;

Use Cases

Opening with a Trigger component

The most common way to open an AlertDialog is by using the AlertDialog.Trigger component. Place it inside the AlertDialog.Root and it will automatically handle opening the dialog when clicked.

Opening with a detached Trigger

When defining the AlertDialog content next to its trigger is not practical, you can use a detached trigger with AlertDialog.createHandle(). This allows you to place the trigger button anywhere in your component tree while still controlling the same dialog instance.

Opening programmatically with state

For complete control over the dialog's visibility, use the open and onOpenChange props on AlertDialog.Root. This is useful when you need to open the dialog based on application logic, such as after an API call or in response to a menu action.

With a form and async submission

AlertDialogs can contain forms with validation. This example shows how to handle async form submission with a loading state on the submit button, keeping the dialog open until the operation completes.