AniUI

Alert Dialog

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

Web preview — components render natively on iOS & Android
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogAction,
  AlertDialogCancel,
} from "@/components/ui/alert-dialog";

export function MyScreen() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <Button onPress={() => setOpen(true)}>Delete Account</Button>
      <AlertDialog open={open} onOpenChange={setOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Are you sure?</AlertDialogTitle>
            <AlertDialogDescription>
              This action cannot be undone. This will permanently delete your account.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onPress={() => setOpen(false)}>Cancel</AlertDialogCancel>
            <AlertDialogAction onPress={() => setOpen(false)}>Continue</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
}

Installation#

npx @aniui/cli add alert-dialog

This component requires react-native-reanimated to be installed in your project.

Usage#

app/index.tsx
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogAction,
  AlertDialogCancel,
} from "@/components/ui/alert-dialog";

export function MyScreen() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <Button onPress={() => setOpen(true)}>Delete Account</Button>
      <AlertDialog open={open} onOpenChange={setOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Are you sure?</AlertDialogTitle>
            <AlertDialogDescription>
              This action cannot be undone. This will permanently delete your account.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel onPress={() => setOpen(false)}>Cancel</AlertDialogCancel>
            <AlertDialogAction onPress={() => setOpen(false)}>Continue</AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
}

Components#

AlertDialog is a compound component made up of several parts:

ComponentDescription
AlertDialog

Root component that manages open state and renders the modal overlay.

AlertDialogContent

The card container for dialog content.

AlertDialogHeader

Wraps the title and description with spacing.

AlertDialogTitle

The heading text of the dialog.

AlertDialogDescription

Descriptive text explaining the action.

AlertDialogFooter

Wraps action buttons with proper layout.

AlertDialogAction

Primary action button (confirm).

AlertDialogCancel

Secondary cancel button (dismiss).

Props#

AlertDialog#

PropTypeDefault
open
boolean
required
onOpenChange
(open: boolean) => void
required
children
React.ReactNode
required

Sub-components (AlertDialogContent, AlertDialogHeader, etc.) accept className and their respective React Native base props.

Accessibility#

  • Uses Modal with Reanimated animations
  • accessibilityRole="alert" on content for screen reader announcements.

Source#

components/ui/alert-dialog.tsx
import React from "react";
import { View, Pressable, Text, Modal } from "react-native";
import Animated from "react-native-reanimated";
import { entering, exiting } from "@/components/ui/animate";
import { cn } from "@/lib/utils";

export interface AlertDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  children: React.ReactNode;
}

export function AlertDialog({ open, onOpenChange, children }: AlertDialogProps) {
  return (
    <Modal visible={open} transparent animationType="none" onRequestClose={() => onOpenChange(false)}>
      <Animated.View entering={entering.fadeIn} exiting={exiting.fadeOut} className="flex-1 items-center justify-center bg-black/50">
        <Animated.View entering={entering.zoomIn} exiting={exiting.zoomOut}>
          {children}
        </Animated.View>
      </Animated.View>
    </Modal>
  );
}

export function AlertDialogContent({ className, children, ...props }: React.ComponentPropsWithoutRef<typeof View> & { className?: string; children?: React.ReactNode }) {
  return (
    <View className={cn("mx-6 w-80 rounded-lg bg-card p-6 shadow-xl", className)} accessibilityRole="alert" {...props}>
      {children}
    </View>
  );
}

export function AlertDialogHeader({ className, ...props }: React.ComponentPropsWithoutRef<typeof View> & { className?: string }) {
  return <View className={cn("pb-4", className)} {...props} />;
}

export function AlertDialogTitle({ className, ...props }: React.ComponentPropsWithoutRef<typeof Text> & { className?: string }) {
  return <Text className={cn("text-lg font-semibold text-card-foreground", className)} {...props} />;
}

export function AlertDialogDescription({ className, ...props }: React.ComponentPropsWithoutRef<typeof Text> & { className?: string }) {
  return <Text className={cn("text-sm text-muted-foreground mt-1", className)} {...props} />;
}

export function AlertDialogFooter({ className, ...props }: React.ComponentPropsWithoutRef<typeof View> & { className?: string }) {
  return <View className={cn("flex-row justify-end gap-3 pt-4", className)} {...props} />;
}

export function AlertDialogAction({ className, children, ...props }: React.ComponentPropsWithoutRef<typeof Pressable> & { className?: string; children: React.ReactNode }) {
  return (
    <Pressable className={cn("items-center justify-center rounded-md bg-primary px-4 py-2.5 min-h-12", className)} accessible={true} accessibilityRole="button" {...props}>
      {typeof children === "string" ? <Text className="text-sm font-medium text-primary-foreground">{children}</Text> : children}
    </Pressable>
  );
}

export function AlertDialogCancel({ className, children, ...props }: React.ComponentPropsWithoutRef<typeof Pressable> & { className?: string; children: React.ReactNode }) {
  return (
    <Pressable className={cn("items-center justify-center rounded-md border border-input px-4 py-2.5 min-h-12", className)} accessible={true} accessibilityRole="button" {...props}>
      {typeof children === "string" ? <Text className="text-sm font-medium text-foreground">{children}</Text> : children}
    </Pressable>
  );
}