How to Resolve Issues with Shadcn UI Dialog in Dropdown Menus

Introduction

Shadcn UI offers a set of beautifully designed, accessible components and a platform for sharing code. I really enjoy building UIs with Shadcn UI because it provides access to all the components you install. It's become one of my favorite tools. However, there's a little hiccup if you try to use a Shadcn UI dialog inside a dropdown menu. Clicking the dialog trigger inside a dropdown menu closes both the dialog and the dropdown, instead of showing the alert dialog. Let's work through fixing this issue step by step.

Before we dive into the solution, let's understand what's causing the problem.

What is the root of the cause?

Is this an issue within Shadcn UI? Nope, it's actually due to an underlying accessible component from Radix UI. Radix UI offers unstyled accessible components, allowing you to style your UI components however you like without having to worry about accessibility.

The code and the issue

Here’s how the current code for the dropdown menu with an alert dialog inside looks like:

import {
  AlertDialog,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { DotsHorizontalIcon } from "@radix-ui/react-icons";
import { Pencil, Trash } from "lucide-react";

const PostActions = () => {
  return (
    <div className="h-screen flex items-center justify-center">
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button size="icon">
            <DotsHorizontalIcon />
          </Button>
        </DropdownMenuTrigger>

        <DropdownMenuContent>
          <DropdownMenuItem>
            <Pencil />
            Edit Post
          </DropdownMenuItem>

          {/* Delete post dropdown menu item with alert dialog */}
          <AlertDialog>
            <AlertDialogTrigger asChild>
              <DropdownMenuItem className="text-destructive">
                <Trash />
                Delete Post
              </DropdownMenuItem>
            </AlertDialogTrigger>
            <AlertDialogContent>
              <AlertDialogHeader className="pb-4">
                <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
                <AlertDialogDescription className="text-[15px]">
                  This action cannot be undone. This will permanently delete
                  your account and remove your data from our servers.
                </AlertDialogDescription>
              </AlertDialogHeader>
              <AlertDialogFooter>
                <Button variant="outline">Cancel</Button>
                <Button variant="destructive">Delete</Button>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </DropdownMenuContent>
      </DropdownMenu>
    </div>
  );
};

export default PostActions;

Output:

When you click the dropdown trigger, the alert dialog pops up for a moment and then goes away. Plus, you won't be able to open the dropdown menu by clicking the trigger again.

Wrap AlertDialogTrigger inside DropdownMenuItem

<AlertDialog>
  <DropdownMenuItem className="text-destructive" asChild>
    <AlertDialogTrigger>
      <Trash />
      Delete Post
    </AlertDialogTrigger>
  </DropdownMenuItem>
  <AlertDialogContent>
    <AlertDialogHeader className="pb-4">
      <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
      <AlertDialogDescription className="text-[15px]">
        This action cannot be undone. This will permanently delete
        your account and remove your data from our servers.
      </AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <Button variant="outline">Cancel</Button>
      <Button variant="destructive">Delete</Button>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>

Output:

Clicking the dropdown trigger won't keep the alert dialog open, but it does let you open the dropdown menu again.

Warning: Performing this step changes the style of the dropdown menu item a little bit. To fix it, apply the class name w-full to the AlertDialogTrigger.

Wrap the whole DropdownMenu inside AlertDialog

<AlertDialog>
  <DropdownMenu>
    <DropdownMenuTrigger asChild>
      <Button size="icon">
        <DotsHorizontalIcon />
      </Button>
    </DropdownMenuTrigger>

    <DropdownMenuContent>
      <DropdownMenuItem>
        <Pencil />
        Edit Post
      </DropdownMenuItem>

      {/* Delete post dropdown menu item with alert dialog */}
      <DropdownMenuItem className="text-destructive" asChild>
        <AlertDialogTrigger>
          <Trash />
          Delete Post
        </AlertDialogTrigger>
      </DropdownMenuItem>
      <AlertDialogContent>
        <AlertDialogHeader className="pb-4">
          <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
          <AlertDialogDescription className="text-[15px]">
            This action cannot be undone. This will permanently delete your
            account and remove your data from our servers.
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogCancel>Cancel</AlertDialogCancel>
          <AlertDialogAction>Delete</AlertDialogAction>
        </AlertDialogFooter>
      </AlertDialogContent>
    </DropdownMenuContent>
  </DropdownMenu>
</AlertDialog>

Output:

Clicking the dropdown trigger doesn't keep the alert dialog open the first time, but if you click it again, the alert dialog stays open.

Final Change: Move the AlertDialogContent outside the DropdownMenu

<AlertDialog>
  <DropdownMenu>
    <DropdownMenuTrigger asChild>
      <Button size="icon">
        <DotsHorizontalIcon />
      </Button>
    </DropdownMenuTrigger>

    <DropdownMenuContent>
      <DropdownMenuItem>
        <Pencil />
        Edit Post
      </DropdownMenuItem>

      {/* Delete post dropdown menu item with alert dialog */}
      <DropdownMenuItem className="text-destructive" asChild>
        <AlertDialogTrigger>
          <Trash />
          Delete Post
        </AlertDialogTrigger>
      </DropdownMenuItem>
    </DropdownMenuContent>
  </DropdownMenu>
  <AlertDialogContent>
    <AlertDialogHeader className="pb-4">
      <AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
      <AlertDialogDescription className="text-[15px]">
        This action cannot be undone. This will permanently delete your
        account and remove your data from our servers.
      </AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <AlertDialogCancel>Cancel</AlertDialogCancel>
      <AlertDialogAction>Delete</AlertDialogAction>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>

Output:

Congrats! You've successfully fixed the issue. Now, users can open the alert dialog smoothly without any problems.

Conclusion

Integrating a Shadcn UI dialog within a dropdown menu might seem tricky at first because of some unexpected behavior. But don't worry! By following the steps in this article, you can fix the issue and make sure everything works smoothly for users. Just wrap the AlertDialogTrigger and adjust where the AlertDialogContent is placed to keep your UI components functional and accessible. With these tweaks, you can keep enjoying the flexibility and design features of Shadcn UI in your projects. Happy coding!