ui icon indicating copy to clipboard operation
ui copied to clipboard

modal closing automatically when nesting dialogs

Open vitormarkis opened this issue 2 years ago • 15 comments

I'm having a hard time trying to nest dialogs components using Shadcn's component library

Walkthrough: Click on Open button > Click on Profile option

After this I was: expectating to render a alert dialog modal but instead, it flashes the alert modal and closes both dialogs

Possible causes I was thinking:

  • Click on Profile (which is within the dropdown menu component), count as click outside the alert dialog, so it closes automatically
  • Click on Profile closes the dialog after a item is clicked by default, so it closes the first modal, and closes the alert dialog consequently since alert dialog is children of dropdown menu

https://codesandbox.io/p/github/vitormarkis/shadcn-doesnt-stack-dialogs/main?file=/src/pages/index.tsx:32,21

vitormarkis avatar Aug 07 '23 03:08 vitormarkis

Hi @vitormarkis you need to wrap the DropDownMenu into the Dialog and put the DialogContent after closing DropDownMenu

see here

ralicata avatar Aug 07 '23 08:08 ralicata

    <AlertDialog> // moved
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button>Open</Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent>                             // dropdown menu content
            <DropdownMenuLabel>My Account</DropdownMenuLabel>
            <DropdownMenuSeparator />
            <AlertDialogTrigger asChild>
              <DropdownMenuItem>Profile</DropdownMenuItem>
            </AlertDialogTrigger>
          </DropdownMenuContent>
          <AlertDialogContent>                                        // alert dialog content
              <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>
                <AlertDialogCancel>Cancel</AlertDialogCancel>
                <AlertDialogAction>Continue</AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
        </DropdownMenu>
      </AlertDialog>

I moved this way and worked, but doesn't seems scalable, how can i have more nested alert dialogs or dropdown menus (dialogs in general)? They would need to have a Context provider for each, but there is no way to distinguish them which context provider goes to each dialog

Do you know any workarounds? Can you show a little demo?

vitormarkis avatar Aug 07 '23 12:08 vitormarkis

Ok now I understand your requirements. You can use your original code, BUT you can't use DropDownMenuItem as a AlterDialogTrigger. You can use a simple div, a button or others.

I updated the code with an example here

ralicata avatar Aug 07 '23 13:08 ralicata

image

I'm not being able to load your branch, can you try to fix? or provide the code at least so i can run on local?

vitormarkis avatar Aug 07 '23 16:08 vitormarkis

try with this code:

<DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Button>Open</Button>
        </DropdownMenuTrigger>
        <DropdownMenuContent>
          <DropdownMenuLabel>My Account</DropdownMenuLabel>
          <DropdownMenuSeparator />
          <AlertDialog>
            <AlertDialogTrigger asChild>
              <div>Profile</div>
            </AlertDialogTrigger>
            <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>
                <AlertDialogCancel>Cancel</AlertDialogCancel>
                <AlertDialogAction>Continue</AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>

          <AlertDialog>
            <AlertDialogTrigger asChild>
              <div>Delete</div>
            </AlertDialogTrigger>
            <AlertDialogContent>
              <AlertDialogHeader>
                <AlertDialogTitle>
                  Are you absolutely sure to DELETE?
                </AlertDialogTitle>
                <AlertDialogDescription>
                  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>Continue</AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </DropdownMenuContent>
      </DropdownMenu>

ralicata avatar Aug 07 '23 20:08 ralicata

repository link

This is what I was refering, a dropdown that opens a dialog that could has dropdowns inside of it, that opens other modals, and go on I achieved this result using states and switching MenuItems to regular Button

What your thoughts on my code approach?

vitormarkis avatar Aug 08 '23 01:08 vitormarkis

How to close the dropdown menu when I click on the item that opens the dialog ? Is that possible ?

louisthomaspro avatar Aug 08 '23 06:08 louisthomaspro

How to close the dropdown menu when I click on the item that opens the dialog ? Is that possible ?

I think you may set the dropdown display as hidden, so it doesn't interfere with the rest of the context/virtual dom logic, I've seen a solution using this approach, but you may need to use state

vitormarkis avatar Aug 08 '23 07:08 vitormarkis

<DropdownMenu {...(isDialogOpened && isDropdownOpend ? { open: false } : null)} onOpenChange={(open) => setIsDropdownOpened(open)} >

Doesn't work

taro-ishihara avatar Oct 30 '23 10:10 taro-ishihara

The solution is to not integrate the AlertDialog component into the DropDownMenuItem component and to use the props open and openOnChange to control the open state from outside. Don't forget do not use AlertDialogTrigger component in AlertDialog if not you can make optional.

      <AlertDialog
        open={open}
        onOpenChange={onOpenChange}
      >       
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>
              title
            </AlertDialogTitle>
            <AlertDialogDescription>
              description
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction> Continue </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>


      <DropdownMenu>
        <DropdownMenuTrigger asChild>
          <Avatar
            className="cursor-pointer"
          >
            <AvatarFallback>U</AvatarFallback>
          </Avatar>
        </DropdownMenuTrigger>

        <DropdownMenuContent
          className="w-48"
        >
          <DropdownMenuLabel>User</DropdownMenuLabel>
          <DropdownMenuSeparator/>
          <DropdownMenuItem
            onClick={() => setOpenAlert(true)}
          >
            Logout
          </DropdownMenuItem>
        </DropdownMenuContent>
      </DropdownMenu>
    </>

atchakpa avatar Nov 10 '23 11:11 atchakpa

Just remove the surrounding DropdownMenuItem and place the Dialog as an item with no surrounding <DropdownMenuItem> and it will work.

raamponsah avatar Nov 19 '23 01:11 raamponsah

add a asChild attribute on the <DropdownMenuItem> like this <DropdownMenuItem asChild> and inside put your alertModal. Kinda strange but simple solution i found out JUST NOW !

image

JoyShaheb avatar Nov 26 '23 15:11 JoyShaheb

add a asChild attribute on the <DropdownMenuItem> like this <DropdownMenuItem asChild> and inside put your alertModal. Kinda strange but simple solution i found out JUST NOW !

image

Where is the trigger here ?

zacBkh avatar Jan 02 '24 03:01 zacBkh

I just faced the same issue so I replaced the DropdownMenuItem by Button component: <Button variant="ghost" className="text-red-500 focus:text-red-500"> Delete issue </Button>

I did not like the workaround but ...

BenaliDjamel avatar Jan 22 '24 09:01 BenaliDjamel

@JoyShaheb You're awesome! worked for me

BrainyWayne avatar Apr 23 '24 13:04 BrainyWayne

Just remove the surrounding DropdownMenuItem and place the Dialog as an item with no surrounding <DropdownMenuItem> and it will work.

this works for me well done man and its the most easy one to apply 👏👏👏

RyuzakiiL23 avatar Jun 16 '24 20:06 RyuzakiiL23

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Jul 09 '24 23:07 shadcn