Skip to content

Dialog.Trigger does not work if trigger is Dropdown.Item #1836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
KevinMusgrave opened this issue Dec 15, 2022 · 84 comments
Closed

Dialog.Trigger does not work if trigger is Dropdown.Item #1836

KevinMusgrave opened this issue Dec 15, 2022 · 84 comments

Comments

@KevinMusgrave
Copy link

Bug report

Current Behavior

A dropdown menu consists of several Dropdown.Item components. If I pass one of these Item components to a Dialog.Trigger, it does not open the dialog on click. If I pass plain text to the Dialog.Trigger, then it works.

Expected behavior

I expect Dropdown.Item to be a valid Dialog.Trigger.

Reproducible example

https://codesandbox.io/s/shy-hill-5ymyp0?file=/src/App.js

Your environment

See sandbox for package versions.

@KevinMusgrave
Copy link
Author

Wrapping Dropdown with Dialog fixes this:

      <Dialog.Root>
        <DropdownMenu.Root>
          <DropdownMenu.Trigger>Dropdown Menu</DropdownMenu.Trigger>
          <DropdownMenu.Portal>
            <DropdownMenu.Content>
              <Dialog.Trigger>
                <DropdownMenu.Item>"Test"</DropdownMenu.Item>
              </Dialog.Trigger>
            </DropdownMenu.Content>
          </DropdownMenu.Portal>
        </DropdownMenu.Root>
        <Dialog.Portal>
          <Dialog.Overlay className="DialogOverlay" />
          <Dialog.Content className="DialogContent">
            This is a modal.
          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

@monokizsolt
Copy link

Hello,

Is there a way to have multiple Dropdown.Item components each with their own Dialog? With your solution only 1 dialog can be opened.

Thanks

@KevinMusgrave
Copy link
Author

KevinMusgrave commented Feb 16, 2023

  1. make each dropdown item set some state on click
  2. pass that state into your dialog component.
  3. render different content inside the dialog component depending on the state

But if you mean open multiple dialogs at the same time, then I don't know.

@joaom00
Copy link
Contributor

joaom00 commented Feb 16, 2023

Hi @monokizsolt, here some examples that can help

https://codesandbox.io/embed/r9sq1q

@monokizsolt
Copy link

Perfect, thank you!

@MarkShawn2020
Copy link

MarkShawn2020 commented Feb 22, 2023

Thank you ! A clean and nice solution !

@DottChen
Copy link

Thank you!

@Kynno
Copy link

Kynno commented May 15, 2023

For anyone who are still having issue with this, I fixed it by using modal={false} on my DropdownMenu.Root component.

I tried the solution in the sandbox link but I was unable to use it in my code, not sure why. However this modal setting did the trick for me.

Hope it helps!

@AlamMena
Copy link

@Kynno Could you bring us more details? maybe an example

@benoitgrelard
Copy link
Contributor

@AlamMena, here is the correct way to handle composition of Dialog and DropdownMenu: https://codesandbox.io/s/dropdownmenu-dialog-items-r9sq1q

@AlamMena
Copy link

@benoitgrelard Yes, I saw that, but I noticed that the dropmenu doesn't close after the dialog opens.

@benoitgrelard
Copy link
Contributor

It depends on which approach, the sandbox shows 2 different approaches. The first one keeps it open (easier to implement), the second closes it (a bit more work to manage focus correctly).

@0xpolarzero
Copy link

0xpolarzero commented Jun 5, 2023

For anyone who are still having issue with this, I fixed it by using modal={false} on my DropdownMenu.Root component.

I tried the solution in the sandbox link but I was unable to use it in my code, not sure why. However this modal setting did the trick for me.

Hope it helps!

I had an issue where the dialog would open, but then I could not click anything after it was closed. And it would trigger a repetitive Uncaught InternalError: too much recursion error.

This simple solution fixed it. Thanks!

@aaronoceanx
Copy link

@Kynno i tried the solution in the sandbox and it didnt work either , i also tried modal={false} and it did not help, super lost. Are you able to share what you did that got it working ?

@luneShaoGM
Copy link

I prevented the default event in the onSelect event of DropdownMenuItem, so the Dialog can be opened now. The code is as follows:

<DropdownMenu>
  <DropdownMenuTrigger> Dropdown Menu </DropdownMenuTrigger>
  <DropdownMenuContent>
    <Dialog>
      <DialogTrigger asChild>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Test
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        This is a modal.
      </DialogContent>
    </Dialog>
  </DropdownMenuContent>
</DropdownMenu>

@soulbliss
Copy link

soulbliss commented Aug 19, 2023

If anyone has come here from shadcn/ui dialog notes and wondering how to show different dialogs for different menu items

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="ghost" className="h-8 w-8 p-0">
      <span className="sr-only">Open menu</span>
      <MoreHorizontal className="h-4 w-4" />
    </Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="end">
    <DropdownMenuLabel>Actions</DropdownMenuLabel>
    <Dialog>
      <DialogTrigger>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Update item
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Update form</DialogTitle>
          <DialogDescription>
            Here you can add fields to update your form
          </DialogDescription>
        </DialogHeader>
      </DialogContent>
    </Dialog>
    <DropdownMenuSeparator />
    <Dialog>
      <DialogTrigger>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Delete item
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure absolutely sure?</DialogTitle>
          <DialogDescription>
            This action cannot be undone. This will permanently delete
            your account and remove your data from our servers.
          </DialogDescription>
        </DialogHeader>
      </DialogContent>
    </Dialog>
  </DropdownMenuContent>
</DropdownMenu>
 

@Malin88
Copy link

Malin88 commented Aug 21, 2023

If anyone has come here from shadcn/ui dialog notes and wondering how to show different dialogs for different menu items
....

But the expanded menu after opening Dialog does not hide, is there any solution for this?

@soulbliss
Copy link

@Malin88 I have been using this so far, works for me.
Found this here from shadcn/ui issues
Example:


const [open, setOpen] = useState(false);

return <Dialog open={open} onOpenChange={setOpen} />

@VesperQuartz
Copy link

If anyone has come here from shadcn/ui dialog notes and wondering how to show different dialogs for different menu items
....

But the expanded menu after opening Dialog does not hide, is there any solution for this?

Did you find the answer to this? same thing happening here

@mohamedamara1
Copy link

If anyone has come here from shadcn/ui dialog notes and wondering how to show different dialogs for different menu items

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="ghost" className="h-8 w-8 p-0">
      <span className="sr-only">Open menu</span>
      <MoreHorizontal className="h-4 w-4" />
    </Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="end">
    <DropdownMenuLabel>Actions</DropdownMenuLabel>
    <Dialog>
      <DialogTrigger>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Update item
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Update form</DialogTitle>
          <DialogDescription>
            Here you can add fields to update your form
          </DialogDescription>
        </DialogHeader>
      </DialogContent>
    </Dialog>
    <DropdownMenuSeparator />
    <Dialog>
      <DialogTrigger>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Delete item
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure absolutely sure?</DialogTitle>
          <DialogDescription>
            This action cannot be undone. This will permanently delete
            your account and remove your data from our servers.
          </DialogDescription>
        </DialogHeader>
      </DialogContent>
    </Dialog>
  </DropdownMenuContent>
</DropdownMenu>
 

Brilliant! thank you

@EliasOlie
Copy link

If anyone has come here from shadcn/ui dialog notes and wondering how to show different dialogs for different menu items

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="ghost" className="h-8 w-8 p-0">
      <span className="sr-only">Open menu</span>
      <MoreHorizontal className="h-4 w-4" />
    </Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent align="end">
    <DropdownMenuLabel>Actions</DropdownMenuLabel>
    <Dialog>
      <DialogTrigger>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Update item
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Update form</DialogTitle>
          <DialogDescription>
            Here you can add fields to update your form
          </DialogDescription>
        </DialogHeader>
      </DialogContent>
    </Dialog>
    <DropdownMenuSeparator />
    <Dialog>
      <DialogTrigger>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Delete item
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Are you sure absolutely sure?</DialogTitle>
          <DialogDescription>
            This action cannot be undone. This will permanently delete
            your account and remove your data from our servers.
          </DialogDescription>
        </DialogHeader>
      </DialogContent>
    </Dialog>
  </DropdownMenuContent>
</DropdownMenu>
 

Brilliant! thank you

I am using a form, and inside it, the inputs are behaving unexpectedly. When I select one input and change its value, the input content gets automatically selected when I move the cursor

@coded58
Copy link

coded58 commented Sep 13, 2023

same issue but mine is with a popover, i have a form (in a modal dialog) and when user opens the date-picker which uses the popover, the popover closes when i hover on it even before selecting a date

@coded58
Copy link

coded58 commented Sep 13, 2023

copy.mp4

this above behavior

@coded58
Copy link

coded58 commented Sep 13, 2023

copy.mp4
this above behavior

solved this by creating a replica popover component without the portal as both the dialog and popover from shadcn were using the body element

@piotrkulpinski
Copy link

I prevented the default event in the onSelect event of DropdownMenuItem, so the Dialog can be opened now. The code is as follows:

<DropdownMenu>
  <DropdownMenuTrigger> Dropdown Menu </DropdownMenuTrigger>
  <DropdownMenuContent>
    <Dialog>
      <DialogTrigger asChild>
        <DropdownMenuItem onSelect={(e) => e.preventDefault()}>
          Test
        </DropdownMenuItem>
      </DialogTrigger>
      <DialogContent>
        This is a modal.
      </DialogContent>
    </Dialog>
  </DropdownMenuContent>
</DropdownMenu>

This solution is great, but it does not close the dropdown element, as clicking on the Dropdown Item would normally do.
Is there any way to keep that functionality while also allowing to open the Dialog?

@dooart
Copy link

dooart commented Sep 28, 2023

@piotrkulpinski i solved this by making both the Dialog and DropdownMenu controlled. then when the dialog closes, i manually close the dropdown menu

here's an example:

function ItemTableRow({ item, onItemUpdated }: { item: Item; onItemUpdated: () => void }) {
  const [isMenuOpen, setIsMenuOpen] = useState(false);

  return (
    <DropdownMenu open={isMenuOpen} onOpenChange={(isOpen) => setIsMenuOpen(isOpen)}>
      <DropdownMenuTrigger asChild>
        <Button variant="ghost" className="h-8 w-8 p-0">
          <span className="sr-only">Open menu</span>
          <MoreHorizontal className="h-4 w-4" />
        </Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        {/* EditItemDialog is just an abstraction around Dialog - onClose is a custom thing */}
        <EditItemDialog
          item={item}
          onItemSaved={onItemUpdated}
          onClose={() => setIsMenuOpen(false)}
        >
          <DropdownMenuItem
            onSelect={(e) => {
              e.preventDefault();
            }}
          >
            <Edit className="h-4 w-4 mr-2" />
            Edit
          </DropdownMenuItem>
        </EditItemDialog>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

it's a bit wonky, but it works

@DylanTse520
Copy link

DylanTse520 commented Jun 19, 2024

Has anyone tried to combine the Dialog and Drawer components to create a responsive dialog, while still nesting them in a dropdown item? I can't use state because I'm using the dropdown item in the table. What I do is to create three abstractions for the wrapper, the trigger and the content, that just return either <Dialog> or <Drawer> based on media query. Not sure if there's a better way...

"use client";

import { useMediaQuery } from "@hooks/use-media-query";

import { Dialog, DialogTrigger } from "@components/ui/dialog";
import { Drawer, DrawerTrigger } from "@components/ui/drawer";

const ResponsiveModal = ({
  isOpen,
  setIsOpen,
  children,
}: {
  isOpen?: boolean;
  setIsOpen?: (isOpen: boolean) => void;
  children: React.ReactNode;
}) => {
  const isDesktop = useMediaQuery("(min-width: 640px)");

  if (isDesktop) {
    return (
      <Dialog open={isOpen} onOpenChange={setIsOpen}>
        {children}
      </Dialog>
    );
  } else {
    return (
      <Drawer open={isOpen} onOpenChange={setIsOpen}>
        {children}
      </Drawer>
    );
  }
};

const ResponsiveModalTrigger = ({
  asChild,
  children,
}: {
  asChild?: boolean;
  children: React.ReactNode;
}) => {
  const isDesktop = useMediaQuery("(min-width: 640px)");

  if (isDesktop) {
    return <DialogTrigger asChild={asChild}>{children}</DialogTrigger>;
  } else {
    return <DrawerTrigger asChild={asChild}>{children}</DrawerTrigger>;
  }
};

export { ResponsiveModal, ResponsiveModalTrigger };

@msruan
Copy link

msruan commented Jun 20, 2024

I went with a different approach for this. Create a dialog as normal, and then put some hidden div as a trigger with a ref:

const triggerRef = useRef<HTMLDivElement>(null);

...

<Dialog.Root>

  <Dialog.Trigger>
    <div className='hidden' ref={triggerRef} />
  <Dialog.Trigger />

  ...

</Dialog.Root>

Then send a click event to this div on the onSelect event of the DropdownMenu.Item:

<DropdownMenu.Root>

  ...

  <DropdownMenu.Item onSelect={() => {
    triggerRef.current?.click();
  }}>

</DropdownMenu.Root>

YOU DID IT!!!!
LOVE U BRO

@kamyarkaviani
Copy link

YOU DID IT!!!! LOVE U BRO

Thanks, but I have to say this is not really ideal. What I've done is imperative and not congruent with React's declarative paradigm. It would be more ideal to instead wrap the dropdown menu inside of one big dialog component with multiple triggers, and change the content of the dialog depending on which item was selected (which you can track with a state). But since I already had the dialogs built out, this was a quick workaround.

@dancork
Copy link

dancork commented Jul 1, 2024

I went with a different approach for this. Create a dialog as normal, and then put some hidden div as a trigger with a ref:

const triggerRef = useRef<HTMLDivElement>(null);

...

<Dialog.Root>

  <Dialog.Trigger>
    <div className='hidden' ref={triggerRef} />
  <Dialog.Trigger />

  ...

</Dialog.Root>

Then send a click event to this div on the onSelect event of the DropdownMenu.Item:

<DropdownMenu.Root>

  ...

  <DropdownMenu.Item onSelect={() => {
    triggerRef.current?.click();
  }}>

</DropdownMenu.Root>

This solution won't apply the correct aria-labels either to the dropdown menu item.

@Kendaichi
Copy link

@juanrgon that's clean ☺️ but just a heads up that you're breaking a11y there so if you're worried about that, i think the most relevant part is to make sure you return focus to the trigger when the dialog closes.

export function useDialog() {
  const [isOpen, setIsOpen] = useState(false);
  const triggerRef = React.useRef();
  
  function trigger() {
    setIsOpen(true);
  }

  function dismiss() {
    setIsOpen(false);
    triggerRef.current?.focus();
  }

  return {
    triggerProps: {
      ref: triggerRef,
      onClick: trigger,
    },
    dialogProps: {
      open: isOpen,
      onOpenChange: open => {
        if (open) trigger();
        else dismiss();
      },
    },
    trigger,
    dismiss,
  };
}
import { Dialog, DialogContent } from "@radix-ui/react-dialog";
import { useDialog } from "@/components/ui/use-dialog.tsx"

function MyComponent() {
  const infoDialog = useDialog();
  return (
    <>
      <button {...infoDialog.triggerProps}>Launch the info dialog</button>
      <Dialog {...infoDialog.dialogProps}>
        <DialogContent> Info </DialogContent>
      </Dialog>
    </>
  );
}

this is why radix usually recommends using the parts they provide instead of doing your own thing, because we can't know for sure what a11y support we're losing by breaking away from them.

Hey! Good day, what if the dialog is inside a looping function. I am trying to display a table, and each corresponding row have a edit button. What arises with using this hook is that multiple dialogs are being rendered, suppose I have 3 rows of data, and I click edit on one of them, 3 dialogs will also be rendered. Sorry for disturbing, I am just trying to learn.

@juanrgon
Copy link

@Kendaichi My guess would be that you're reusing the same useDialog trigger on each of your edit buttons. Each edit button will need its own useDialog call, so you may want to create a child component for your edit button to make this simpler:

function Table() {
  return {rows.map(r => <tr><Edit/></tr>)}
}

function Edit() {
  const dialog = useDialog();
  return <>
      <button {...dialog.triggerProps}>Edit</button>
      <Dialog {...dialog.dialogProps}>
        <DialogContent> Edit </DialogContent>
      </Dialog>
  </>
}

@tsleblanc
Copy link

Similar to some previous answers, but using a more generic hook.

// @/hooks/use-show-hide.js
import { useState } from 'react';

export const useShowHide = (defaultVisible = false) => {
  const [visible, setVisible] = useState(defaultVisible);

  const show = () => setVisible(true);
  const hide = () => setVisible(false);

  const toggle = (nextVisible) => {
    if (typeof nextVisible !== 'undefined') {
      setVisible(nextVisible);
    } else {
      setVisible((previousVisible) => !previousVisible);
    }
  };

  return { hide, show, toggle, visible };
};


// dropdown-menu.jsx
import { useParams } from 'react-router-dom';
import { deletePost } from '@/api/post';
import { ConfirmDialog } from '@/components/confirm-dialog';
import { useShowHide } from '@/hooks/use-show-hide';

export function DropdownMenu() {
  const { id } = useParams();

  const deleteDialog = useShowHide();

  const handleDelete = () =>
    deletePost(id)
      .catch(() => {
        alert('Post deletion has failed.');
      })
      .then(() => {
        deleteDialog.hide();
      });

  return (
    <>
      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <MenuButton />
        </DropdownMenuTrigger>
        <DropdownMenuContent>
          <DropdownMenuItem>View details</DropdownMenuItem>
          <DropdownMenuSeparator />
          <DropdownMenuItem
            className="!text-destructive"
            onSelect={deleteDialog.show}
          >
            Delete
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>

      <Dialog onOpenChange={deleteDialog.toggle} open={deleteDialog.visible}>
        <DialogContent>
          <ConfirmDialog
            onSubmit={handleDelete}
            title="Are you sure to delete this post?"
          />
        </DialogContent>
      </Dialog>
    </>
  );
}

erikgoranson added a commit to erikgoranson/budget-tool that referenced this issue Aug 26, 2024
- also tried using the shadcnvue dropdown menu but decided against it due to an existing bug when nesting drawers/dialogs, radix-ui/primitives#1836
@sibananda485
Copy link

modal={false}

Thanks a a lot man it solved my issue

@knakmitch
Copy link

knakmitch commented Oct 16, 2024

I'm not a huge fan of highly nested templates, and wanted a way to remotely trigger the modal., so I created a component to remotely trigger the dialog to open. This method allows me to host ConfirmDialog outside of DropdownMenu.

// MyDropdownMenu.vue
<template>
  <DropdownMenu>
    <DropdownMenuTrigger>
      <slot>
        <IconButton icon="more-vert" />
      </slot>
    </DropdownMenuTrigger>
    <DropdownMenuContent>
      <DropdownMenuItem @click="remoteDeleteTrigger = true"> <Icon name="delete" />Delete </DropdownMenuItem>
    </DropdownMenuContent>
  </DropdownMenu>

  <ConfirmDialog
    title="Delete Thing"
    message="Are you sure you want to delete this thing?"
    @confirm="...do something"
  >
    <RemoteDialogTrigger v-model="remoteDeleteTrigger" />
  </ConfirmDialog>
</template>

<script setup lang="ts">
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import IconButton from "../ui/button/IconButton.vue";
import Icon from "../ui/icon/Icon.vue";
import ConfirmDialog from "../dialog/ConfirmDialog.vue";
import RemoteDialogTrigger from "../dialog/RemoteDialogTrigger.vue";
import { ref } from "vue";

const remoteDeleteTrigger = ref<boolean>(false);
</script>
// RemoteDialogTrigger.vue
<template>

<div ref="remote-trigger"></div>

</template>

<script lang="ts" setup>
import { useTemplateRef, watch } from "vue";

const model = defineModel<boolean>();
  const remoteTrigger = useTemplateRef<HTMLElement>('remote-trigger');

watch(model, (value) => {
  if (value) {
    remoteTrigger.value?.click();
    model.value = false;
  }
});

</script>

@tariky
Copy link

tariky commented Oct 29, 2024

For anyone who are still having issue with this, I fixed it by using modal={false} on my DropdownMenu.Root component.

I tried the solution in the sandbox link but I was unable to use it in my code, not sure why. However this modal setting did the trick for me.

Hope it helps!

Thank you so much. This is right solution.

<DropdownMenu modal={false}><DialogComponentWithDropDownItemAsTrigger /></DropdownMenu>

@kontyente
Copy link

For those who use Vue here is a workaround with "as-child" and "@click.stop"
It works as it should.
`

    <DropdownMenuTrigger as-child>
        <Button variant="ghost" class="w-8 h-8 p-0">
            <span class="sr-only">Open menu</span>
            <MoreHorizontal class="w-4 h-4" />
        </Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent align="end">
        <DropdownMenuLabel>Actions</DropdownMenuLabel>

        <DropdownMenuItem>
            <Dialog>
                <DialogTrigger as-child @click.stop>
                    <div class="flex items-center cursor-pointer">
                        <Logs class="mr-2 h-4 w-4" />
                        <span>Logs</span>
                    </div>
                </DialogTrigger>
                <DialogContent class="sm:min-w-[800px]">
                    <DialogHeader>
                        <DialogTitle>Logs</DialogTitle>
                        <DialogDescription>
                            Details about device logs.
                        </DialogDescription>
                    </DialogHeader>
                    <DialogFooter>
                        <Button @click="closeDialog">Close</Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </DropdownMenuItem>
        
    </DropdownMenuContent>
</DropdownMenu>

`

@MSAJAL07
Copy link

MSAJAL07 commented Nov 1, 2024

DropdownMenu

Bro! You're a lifesaver. I spent 2-3 hours trying to figure this out.

@CauaYves
Copy link

CauaYves commented Nov 2, 2024

I resolved by wrapping the Dropdown with AlertDialog and putting the dialog trigger inside of DropDownMenuItem

			<AlertDialog>
				<AlertDialogContent>
					<AlertDialogHeader>
						<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
						<AlertDialogDescription>
							This action cannot be undone. This will permanently delete your
							account and remove your data from our servers.
						</AlertDialogDescription>
					</AlertDialogHeader>
					<AlertDialogFooter>
						<AlertDialogAction>Fechar</AlertDialogAction>
					</AlertDialogFooter>
				</AlertDialogContent>
				<div className="flex justify-end">
					<DropdownMenu modal={false}>
						<DropdownMenuTrigger asChild>
							<Button variant="ghost" className="h-8 w-8 p-0">
								<span className="sr-only">Open menu</span>
								<MoreHorizontal className="h-4 w-4" />
							</Button>
						</DropdownMenuTrigger>
						<DropdownMenuContent>
							<DropdownMenuItem onSelect={(e) => e.preventDefault()}>
								<AlertDialogTrigger 
                                                                      className="flex items-center gap-2 cursor-pointer pointer-events-auto">
									<CircleEllipsis
										size={16}
										className="text-muted-foreground"
									/>
									<P className="text-muted-foreground">Ver detalhes</P>
								</AlertDialogTrigger>
							</DropdownMenuItem>
							<DropdownMenuItem>
								<CircleX size={16} className="text-muted-foreground" />
								<P className="text-muted-foreground">Cancelar matrícula</P>
							</DropdownMenuItem>
						</DropdownMenuContent>
					</DropdownMenu>
				</div>
			</AlertDialog>

@AhmedTharwat-AT
Copy link

This worked for me , if you want to open multiple dialogs within a dropdown menu while closing the menu after selecting a dialog

const [openedDialog, setOpenedDialog] = useState<"delete" | "edit">();
  return (
    <Dialog>
      <DropdownMenu modal={false}>
        <DropdownMenuTrigger asChild>
          <Button variant="ghost" className="h-8 w-8 p-0">
            <span className="sr-only">Open menu</span>
            <MoreHorizontal />
          </Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent align="end">
          <DialogTrigger
            asChild
            onClick={() => {
              setOpenedDialog("delete");
            }}
          >
            <DropdownMenuItem>Delete</DropdownMenuItem>
          </DialogTrigger>
          <DialogTrigger
            asChild
            onClick={() => {
              setOpenedDialog("edit");
            }}
          >
            <DropdownMenuItem>Edit</DropdownMenuItem>
          </DialogTrigger>
        </DropdownMenuContent>
      </DropdownMenu>
      <DialogContent>
        {openedDialog === "delete" ? (
          <DeletePropertyModal />
        ) : (
          <EditPropertyModal />
        )}
      </DialogContent>
    </Dialog>
  )

ssanjose added a commit to ssanjose/transact that referenced this issue Dec 14, 2024
… causing improper opening/closing behaviour & erratic highlighting, import use-dialog from radix-ui/primitives#1836 (comment) for fix
@rksahu2610
Copy link

Hello, I found a solution in the ShadCN example from the playground.

https://ui.shadcn.com/examples/playground

Screen.Recording.2025-01-08.184030.mp4

@matthias
Copy link

matthias commented Jan 29, 2025

Hello, I found a solution in the ShadCN example from the playground.

https://ui.shadcn.com/examples/playground

Screen.Recording.2025-01-08.184030.mp4

This example also shows the issue / bug:

  • when you open the dialog "Content Filter Preferences" - and close it again - the UI freezes (doesn't accept any user inputs anymore) - the cause is because <body> still has the pointer-events: none;

<body style="pointer-events: none;">...

So still the most simple solution for me is to prevent the "scroll locking" via <DropdownMenu modal={false}> -> because this is currently not working with nested Dialogs - as they also want to "scroll lock".

As you can also see in the playground: when you open the dropdown - you can not scroll the page anymore - in my use case this feature was not needed - as the dropdown can stay open when I scroll (it will be repositioned correctly when you scroll)

@juanrgon
Copy link

Perhaps this issue should be locked, as the comments have largely devolved into reposts of previously suggested solutions

@caturbgs
Copy link

For those who use Vue here is a workaround with "as-child" and "@click.stop" It works as it should. `

    <DropdownMenuTrigger as-child>
        <Button variant="ghost" class="w-8 h-8 p-0">
            <span class="sr-only">Open menu</span>
            <MoreHorizontal class="w-4 h-4" />
        </Button>
    </DropdownMenuTrigger>
    <DropdownMenuContent align="end">
        <DropdownMenuLabel>Actions</DropdownMenuLabel>

        <DropdownMenuItem>
            <Dialog>
                <DialogTrigger as-child @click.stop>
                    <div class="flex items-center cursor-pointer">
                        <Logs class="mr-2 h-4 w-4" />
                        <span>Logs</span>
                    </div>
                </DialogTrigger>
                <DialogContent class="sm:min-w-[800px]">
                    <DialogHeader>
                        <DialogTitle>Logs</DialogTitle>
                        <DialogDescription>
                            Details about device logs.
                        </DialogDescription>
                    </DialogHeader>
                    <DialogFooter>
                        <Button @click="closeDialog">Close</Button>
                    </DialogFooter>
                </DialogContent>
            </Dialog>
        </DropdownMenuItem>
        
    </DropdownMenuContent>
</DropdownMenu>

`

doesn't work for me

CrossEvol added a commit to CrossEvol/CE-Dial that referenced this issue Mar 2, 2025
- click Plus can open AddGroup Dialog
- right click on each group button can open context menu
- context menu can set default chosen, edit/delete and manage all the groups, so the context menu can open two different dialogs, one for EditGroup, one for ManageGroup
- ManageGroup can open AddGroup and EditGroup as well
- based on issue radix-ui/primitives#1836 to call multi dialog on shadcn-ui
tzezar added a commit to tzezar/nextjs-recruitment-task that referenced this issue Mar 12, 2025
 approached this task as an opportunity to learn something new, so I decided to give ShadCN UI a try. Unfortunately, I ran into a few tricky bugs while implementing the features. I also considered using Tanstack Table and Tanstack Query, but the scale of the project was too small for that to be necessary.

During the task, I encountered several bugs in ShadCN UI, such as:
shadcn-ui/ui#468
radix-ui/primitives#1836 (comment)
I was able to fix some of these issues, but there's still one remaining problem: after submitting the form, clicking anything becomes impossible. This seems to be related to focus management when dealing with multiple popovers. Since resolving third-party issues is outside the scope of this task, I’m leaving it as is for now. Apologies for the inconvenience! 😅
@danggearment
Copy link

You can resolve this issue by changing the uncontrolled dropdown menu to a controlled dropdown menu and closing the menu item when it is clicked.

@erikwibowo
Copy link

For anyone who are still having issue with this, I fixed it by using modal={false} on my DropdownMenu.Root component.

I tried the solution in the sandbox link but I was unable to use it in my code, not sure why. However this modal setting did the trick for me.

Hope it helps!

thank you so much. you save my day

@kawsar-jvai
Copy link

For anyone who are still having issue with this, I fixed it by using modal={false} on my DropdownMenu.Root component.

I tried the solution in the sandbox link but I was unable to use it in my code, not sure why. However this modal setting did the trick for me.

Hope it helps!

this works for me. thanks

@hilmarch-dev
Copy link

Hello, I found a solution in the ShadCN example from the playground.
https://ui.shadcn.com/examples/playground
Screen.Recording.2025-01-08.184030.mp4

This example also shows the issue / bug:

  • when you open the dialog "Content Filter Preferences" - and close it again - the UI freezes (doesn't accept any user inputs anymore) - the cause is because <body> still has the pointer-events: none;

<body style="pointer-events: none;">...

So still the most simple solution for me is to prevent the "scroll locking" via <DropdownMenu modal={false}> -> because this is currently not working with nested Dialogs - as they also want to "scroll lock".

As you can also see in the playground: when you open the dropdown - you can not scroll the page anymore - in my use case this feature was not needed - as the dropdown can stay open when I scroll (it will be repositioned correctly when you scroll)

Woks for me

@walayatKhan19
Copy link

walayatKhan19 commented May 12, 2025

Adding modal={false} worked for me I want to open dialog from each menu item. It solves the issue blocked aria as well.

<DropdownMenu modal={false}> <DropdownMenuTrigger asChild> <Button variant="ghost" className="h-8 w-8 p-0"> <span className="sr-only">Open Menu</span> <MoreHorizontal className="h-4 w-4" /> </Button> </DropdownMenuTrigger> <DropdownMenuContent align="end"> <DropdownMenuLabel>Actions</DropdownMenuLabel> {bulkActions.map((action, index) => ( <DropdownMenuItem key={index} onClick={() => action.onClick(getSelectedRows())} disabled={table.getSelectedRowModel().rows.length === 0} > {action.label} </DropdownMenuItem> ))} </DropdownMenuContent> </DropdownMenu>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests