tapcn
Components

Dialog

A modal dialog component with overlay and animations.

Dialog

A modal dialog component with overlay, animations, and proper accessibility. Uses @rn-primitives/dialog for cross-platform behavior.

Installation

npx @tapcn/cli add dialog

Or using shadcn directly:

npx shadcn@latest add https://tapcn.vercel.app/r/dialog.json

This will also install the icon and native-only-animated-view components.

Usage

import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '~/components/ui/dialog';
import { Button } from '~/components/ui/button';
import { Text } from '~/components/ui/text';

export function Example() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button variant="outline">
          <Text>Open Dialog</Text>
        </Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure?</DialogTitle>
          <DialogDescription>
            This action cannot be undone. This will permanently delete your
            account and remove your data from our servers.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose asChild>
            <Button variant="outline">
              <Text>Cancel</Text>
            </Button>
          </DialogClose>
          <Button>
            <Text>Continue</Text>
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

Controlled dialog

import { useState } from 'react';

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

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger asChild>
        <Button>
          <Text>Edit Profile</Text>
        </Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Edit Profile</DialogTitle>
          <DialogDescription>
            Make changes to your profile here.
          </DialogDescription>
        </DialogHeader>
        {/* Form fields */}
        <DialogFooter>
          <Button onPress={() => setOpen(false)}>
            <Text>Save changes</Text>
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

Sub-Components

ComponentDescription
DialogRoot component (controlled or uncontrolled)
DialogTriggerButton that opens the dialog
DialogContentThe dialog panel with close button
DialogHeaderGroups title and description
DialogTitleThe dialog heading
DialogDescriptionDescriptive text below the title
DialogFooterAction buttons area
DialogCloseButton that closes the dialog
DialogOverlayBackground overlay (used internally)
DialogPortalPortal wrapper (used internally)

Platform Behavior

  • Web: Uses CSS animations (animate-in, fade-in, zoom-in) for smooth transitions
  • Native: Uses react-native-reanimated (FadeIn, FadeOut) for native-performance animations
  • iOS: Uses FullWindowOverlay from react-native-screens for proper modal stacking

Dependencies

  • icon -- for the close button X icon
  • native-only-animated-view -- for native-only Reanimated animations
  • @rn-primitives/dialog -- underlying primitive
  • react-native-reanimated -- native animations
  • react-native-screens -- iOS FullWindowOverlay
  • lucide-react-native -- X close icon

On this page