Alert Dialog

A modal dialog that interrupts the user with important content and expects a response.


import { Trash } from "lucide-react"
import AlertDialog from "@tailus-ui/AlertDialog"
import Button from "@tailus-ui/Button"

export const Centered = () => (
    <AlertDialog.Root>
      <AlertDialog.Trigger asChild>
        <Button.Root variant="soft" intent="danger">
            <Button.Icon type="leading" size="sm">
                <Trash />
            </Button.Icon>
            <Button.Label>Delete</Button.Label>
        </Button.Root>
      </AlertDialog.Trigger>
      <AlertDialog.Portal>
        <AlertDialog.Overlay />
        <AlertDialog.Content className="max-w-sm" data-shade="800">
            <AlertDialog.Title>
                Are you absolutely sure?
            </AlertDialog.Title>
            <AlertDialog.Description className="mt-2">
                This photo will be deleted from your iCloud Photos.
            </AlertDialog.Description>
            <AlertDialog.Actions>
                <AlertDialog.Cancel asChild>
                    <Button.Root
                        variant="outlined"
                        intent="gray"
                        size="sm"
                    >
                        <Button.Label>Cancel</Button.Label>
                    </Button.Root>
                </AlertDialog.Cancel>
                <AlertDialog.Action asChild>
                    <Button.Root
                        variant="solid"
                        intent="danger"
                        size="sm"
                    >
                        <Button.Label>Yes, Delete</Button.Label>
                    </Button.Root>
                </AlertDialog.Action>
            </AlertDialog.Actions>
        </AlertDialog.Content>
      </AlertDialog.Portal>
    </AlertDialog.Root>
)

Installation

Install the primitive and Copy-Paste the component code in a .tsx file.

npm install @radix-ui/react-alert-dialog
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import React from "react";
import {
  dialog,
  title,
  text,
  type DialogProps,
  type TitleSizeProp,
  type TextProps,
  type TextSizeProp,
  type TextAlignProp,
  type TextWeightProp
} from "@tailus/themer"

interface AlertDialogProps extends React.ComponentProps<typeof AlertDialogPrimitive.Root> {}
const AlertDialogRoot: React.FC<AlertDialogProps> = ({...props}) => {
    return (
        <AlertDialogPrimitive.Root {...props} />
    )
}

const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
const AlertDialogPortal = AlertDialogPrimitive.Portal;

const AlertDialogOverlay = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
  >(({ className, ...props }, forwardedRef) => {
    const { overlay } = dialog()

  return (
    <AlertDialogPrimitive.Overlay
      {...props}
      ref={forwardedRef}
      className={overlay({className})}
    />
  )
})

const AlertDialogContent = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Content>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> & DialogProps
  >(({ className, mixed, fancy, ...props }, forwardedRef) => {
  
  const { content } = dialog()
    
  if (fancy && mixed) {
    throw new Error('The fancy and mixed props cannot be used together.');
  }
    
  return (
    <AlertDialogPrimitive.Content
      {...props}
      ref={forwardedRef}
      className={content({fancy, mixed, className})}
    />
  )
});

const AlertDialogTitle = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title> & {
    size?: TitleSizeProp,
    align?: TextAlignProp,
    weight?: TextWeightProp
  }
>(({className, size="base", weight="medium", align, ...props}, forwardedRef) => {
  return (
    <AlertDialogPrimitive.Title
      {...props}
      ref={forwardedRef}
      className={
        title({
          size,
          weight,
          align,
          className
        })
      }
    />
  )
});

const AlertDialogDescription = React.forwardRef<
  React.ElementRef<typeof AlertDialogPrimitive.Description>,
  React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description> & TextProps & {
    size?: TextSizeProp,
    align?: TextAlignProp,
    weight?: TextWeightProp
  }
>(({className, size="base", weight, align, ...props}, forwardedRef) => {
  return (
    <AlertDialogPrimitive.Description
      {...props}
      ref={forwardedRef}
      className={
        text({
          size,
          weight,
          align,
          className,
        })
      }
    />
  )
});

const AlertDialogCancel = AlertDialogPrimitive.Cancel;
const AlertDialogAction = AlertDialogPrimitive.Action;

const AlertDialogActions = React.forwardRef<
  React.ElementRef<"div">,
  React.ComponentPropsWithoutRef<"div">
  >(({ className, ...props }, forwardedRef) => {
  const { actions } = dialog()
  return (
    <div
      {...props}
      ref={forwardedRef}
      className={actions({className})}
    />
  )
});

export default {
  Root: AlertDialogRoot,
  Trigger: AlertDialogTrigger,
  Portal: AlertDialogPortal,
  Overlay: AlertDialogOverlay,
  Content: AlertDialogContent,
  Title: AlertDialogTitle,
  Description: AlertDialogDescription,
  Cancel: AlertDialogCancel,
  Action: AlertDialogAction,
  Actions: AlertDialogActions,
}

export {
  AlertDialogRoot,
  AlertDialogTrigger,
  AlertDialogPortal,
  AlertDialogOverlay,
  AlertDialogContent,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogCancel,
  AlertDialogAction,
  AlertDialogActions,
}

Usage

Import the AlertDialog parts you need to use in your component and build your AlertDialog.

import AlertDialog from "@tailus-ui/AlertDialog"
import Button from "@tailus-ui/Button"

See examples below for more use cases.

Reference

Content

The content of the AlertDialog component

Prop
Type
Default
mixed
boolean
-
fancy
boolean
-

Title

The title of the AlertDialog component

Prop
Type
Default
size ~
enum
4xl
align ~
enum
left
weight ~
enum

Description

The description of the AlertDialog component

Prop
Type
Default
size ~
enum
base
align ~
enum
left
weight ~
enum

Actions

The parent component of the <Cancel /> and <Action /> parts.

Examples

Centered


import { Trash } from "lucide-react"
import AlertDialog from "@tailus-ui/AlertDialog"
import Button from "@tailus-ui/Button"

export const Centered = () => (
    <AlertDialog.Root>
      <AlertDialog.Trigger asChild>
        <Button.Root variant="soft" intent="danger">
            <Button.Icon type="leading" size="sm">
                <Trash />
            </Button.Icon>
            <Button.Label>Delete</Button.Label>
        </Button.Root>
      </AlertDialog.Trigger>
      <AlertDialog.Portal>
        <AlertDialog.Overlay />
        <AlertDialog.Content className="max-w-md" data-shade="800">
            <AlertDialog.Title align="center">
                Are you absolutely sure?
            </AlertDialog.Title>
            <AlertDialog.Description align="center" className="mt-2">
                This photo will be deleted from your iCloud Photos.
            </AlertDialog.Description>
            <AlertDialog.Actions className="justify-center">
                <AlertDialog.Cancel asChild>
                    <Button.Root
                        variant="outlined"
                        intent="gray"
                        size="sm"
                    >
                        <Button.Label>Cancel</Button.Label>
                    </Button.Root>
                </AlertDialog.Cancel>
                <AlertDialog.Action asChild>
                    <Button.Root
                        variant="solid"
                        intent="danger"
                        size="sm"
                    >
                        <Button.Label>Yes, Delete</Button.Label>
                    </Button.Root>
                </AlertDialog.Action>
            </AlertDialog.Actions>
        </AlertDialog.Content>
      </AlertDialog.Portal>
    </AlertDialog.Root>
)

iOS


import { Trash } from "lucide-react"
import AlertDialog from "@tailus-ui/AlertDialog"
import Button from "@tailus-ui/Button"
import SeparatorRoot from "@tailus-ui/Separator"

export const IOs = () => (
    <AlertDialog.Root>
      <AlertDialog.Trigger asChild>
        <Button.Root variant="soft" intent="danger">
            <Button.Icon type="leading" size="sm">
                <Trash />
            </Button.Icon>
            <Button.Label>Delete</Button.Label>
        </Button.Root>
      </AlertDialog.Trigger>
      <AlertDialog.Portal>
        <AlertDialog.Overlay />
            <AlertDialog.Content className="overflow-hidden p-0 max-w-[18rem]" data-shade="800">
                <div className="p-[--feedback-padding] text-center">
                    <AlertDialog.Title align="center">
                        Are you absolutely sure?
                    </AlertDialog.Title>
                    <AlertDialog.Description align="center" className="mt-2">
                        This photo will be deleted from your iCloud Photos.
                    </AlertDialog.Description>
                </div>
                <div>
                    <SeparatorRoot />
                    <AlertDialog.Actions className="mt-0 overflow-hidden gap-0 h-full">
                        <AlertDialog.Cancel asChild>
                            <Button.Root
                                variant="ghost"
                                intent="gray"
                                size="md"
                                className="rounded-none w-1/2"
                            >
                                <Button.Label>Cancel</Button.Label>
                            </Button.Root>
                        </AlertDialog.Cancel>
                        <SeparatorRoot orientation="vertical" className="h-9" />
                        <AlertDialog.Action asChild>
                            <Button.Root
                                variant="ghost"
                                intent="danger"
                                size="md"
                                className="rounded-none w-1/2"
                            >
                                <Button.Label>Yes, Delete</Button.Label>
                            </Button.Root>
                        </AlertDialog.Action>
                    </AlertDialog.Actions>
                </div>
        </AlertDialog.Content>
      </AlertDialog.Portal>
    </AlertDialog.Root>
)

Mixed Content

<AlertDialog.Content mixed data-shade="800">

Fancy Content

<AlertDialog.Content fancy data-shade="800">

Glassy Content

<AlertDialog.Content data-shade="glassy">
<AlertDialog.Content mixed data-shade="glassy">
<AlertDialog.Content fancy data-shade="glassy">