ui
ui copied to clipboard
I can't click anywhere after using alert dialog.
I wanted to implement alert-dialog into my dropdown menu but after I click to buttons I can't click anymore I had to refresh site.
code:
"use client"
import { ColumnDef } from "@tanstack/react-table"
import { ArrowUpDown, Eye, EyeOff, MoreHorizontal } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import { useRouter, useSearchParams } from "next/navigation"
import { useState } from "react"
export type Category = {
id: string
name: string
products: number
visibility: "public" | "private"
}
export const columns: ColumnDef<Category>[] = [
{
id: "select",
header: ({ table }) => (
<Checkbox
checked={table.getIsAllPageRowsSelected()}
onCheckedChange={(value:any) => table.toggleAllPageRowsSelected(!!value)}
aria-label="Select all"
/>
),
cell: ({ row }) => (
<Checkbox
checked={row.getIsSelected()}
onCheckedChange={(value:any) => row.toggleSelected(!!value)}
aria-label="Select row"
/>
),
enableSorting: false,
enableHiding: false,
},
{
accessorKey: "name",
header: "Kategori",
cell: ({ row }) => <div>{row.getValue("name")}</div>,
},
{
accessorKey: "products",
header: "Ürün Sayısı",
cell: ({ row }) => <div>{row.getValue("products")}</div>,
},
{
accessorKey: "visibility",
header: "Görünürlük",
cell: ({ row }) => (
<div>
{row.getValue("visibility") === "public" ?
<><Eye className="mr-2 inline flex-1 text-sm text-muted-foreground" size={20}/>Herkese açık</> :
<><EyeOff className="mr-2 inline flex-1 text-sm text-muted-foreground" size={20}/>Gizli</>
}
</div>
),
},
{
id: "actions",
enableHiding: false,
cell: ({ row }) => {
const category = row.original
// eslint-disable-next-line react-hooks/rules-of-hooks
const router = useRouter()
const handleDelete = () => {
// Perform delete action here
// For example:
// deleteCategory(category.id)
// .then(() => router.push('/categories'))
}
// eslint-disable-next-line react-hooks/rules-of-hooks
const [isAlertDialogOpen, setAlertDialogOpen] = useState(false)
return (
<>
<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>Eylemler</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => setAlertDialogOpen(true)}>Kategoriyi Sil</DropdownMenuItem>
<DropdownMenuItem onClick={() => router.push(`/categories/edit/${category.id}`)}>Katogori Görünürlük</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={() => router.push(`/categories/edit/${category.id}`)}>Kategoriyi Düzenle</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<AlertDialog open={isAlertDialogOpen} onOpenChange={setAlertDialogOpen}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Emin misiniz?</AlertDialogTitle>
<AlertDialogDescription>
Bu eylem geri alınamaz. Bu eylem kategoriyi kalıcı olarak silecek.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel onClick={() => setAlertDialogOpen(false)}>İptal</AlertDialogCancel>
<AlertDialogAction>Devam et</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
)
},
},
]
Me too I have the same issue.
I took the implementation from taxonomy,
the dialog / dialog-alert inside a select will disable the click events exept for text selection :) after i close the dialog
Hi @wCatly and @UnknownBigBrain, did you try this?
"To activate the Dialog component from within a Context Menu or Dropdown Menu, you must encase the Context Menu or Dropdown Menu component in the Dialog component. For more information, refer to the linked issue here."
From the documentation here: https://ui.shadcn.com/docs/components/dialog
Hi @wCatly and @UnknownBigBrain, did you try this?
"To activate the Dialog component from within a Context Menu or Dropdown Menu, you must encase the Context Menu or Dropdown Menu component in the Dialog component. For more information, refer to the linked issue here."
From the documentation here: https://ui.shadcn.com/docs/components/dialog
Hi @samjowen thx for the response. Popover worked but Menu still have the same issue
Popover: `
<Dialog open={showDeleteAlert} onOpenChange={setShowDeleteAlert}>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger className="flex h-8 w-8 items-center justify-center rounded-md border transition-colors hover:bg-muted">
<Icons.ellipsis className="h-4 w-4" />
<span className="sr-only">Open</span>
</PopoverTrigger>
<PopoverContent className="w-[200px] p-0">
<Button
className="flex cursor-pointer items-center text-destructive focus:text-destructive"
onClick={() => setShowDeleteAlert(true)}
>
Delete
</Button>
</PopoverContent>
</Popover>
<DialogContent>
<DialogHeader>
<DialogTitle>
Are you sure you want to delete this post?
</DialogTitle>
<DialogDescription>
This action cannot be undone.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogTrigger>Cancel</DialogTrigger>
<DialogTrigger
onClick={async (event) => {
event.preventDefault();
setIsDeleteLoading(true);
// const deleted = await deletePost(post.id)
// if (deleted) {
setIsDeleteLoading(false);
setShowDeleteAlert(false);
router.refresh();
// }
}}
className="bg-red-600 focus:ring-red-600"
>
{isDeleteLoading ? (
<Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
) : (
<Icons.trash className="mr-2 h-4 w-4" />
)}
<span>Delete</span>
</DialogTrigger>
</DialogFooter>
</DialogContent>
</Dialog>
`
Menu: `
<Dialog open={showDeleteAlert} onOpenChange={setShowDeleteAlert}>
<DropdownMenu>
<DropdownMenuTrigger>
<Icons.ellipsis className="h-4 w-4" />
<span className="sr-only">Open</span>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>
<Link
href={`/editor/${product.id}`}
className="flex w-full"
>
Edit
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
className="flex cursor-pointer items-center text-destructive focus:text-destructive"
onSelect={() => setShowDeleteAlert(true)}
>
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<DialogContent>
<DialogHeader>
<DialogTitle>
Are you sure you want to delete this post?
</DialogTitle>
<DialogDescription>
This action cannot be undone.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogTrigger>Cancel</DialogTrigger>
<DialogTrigger
onClick={async (event) => {
event.preventDefault();
setIsDeleteLoading(true);
// const deleted = await deletePost(post.id)
// if (deleted) {
setIsDeleteLoading(false);
setShowDeleteAlert(false);
router.refresh();
// }
}}
className="bg-red-600 focus:ring-red-600"
>
{isDeleteLoading ? (
<Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
) : (
<Icons.trash className="mr-2 h-4 w-4" />
)}
<span>Delete</span>
</DialogTrigger>
</DialogFooter>
</DialogContent>
</Dialog>
`
'use client'
import { DropdownMenuTrigger } from '@radix-ui/react-dropdown-menu'
import { SlidersHorizontal } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuItem,
} from '@/components/ui/dropdown-menu'
import { Dialog, DialogTrigger } from '@/components/ui/dialog'
import { AddGroupDialogContent } from '../../forms/components/add-group-dialog-content'
import { Sheet, SheetTrigger } from '@/components/ui/sheet'
import { AddItemSheetContent } from '../../forms/components/add-item-sheet-content'
import { EstimateType } from '@prisma/client'
import React from 'react'
export function AddItemsDropdown() {
const [openSheet, setOpenSheet] = React.useState<boolean>(false)
const [itemType, setItemType] = React.useState<EstimateType>('MATERIAL')
return (
<div>
<Dialog>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant='outline' size='sm' className='ml-auto hidden h-8 lg:flex'>
<SlidersHorizontal className='mr-2 h-4 w-4' />
Add Items
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align='end' className='w-[150px]'>
<DropdownMenuLabel>Add Items</DropdownMenuLabel>
<DialogTrigger className='w-full'>
<DropdownMenuItem>{'Add Group'}</DropdownMenuItem>
</DialogTrigger>
<DropdownMenuItem
onSelect={() => {
setOpenSheet(true)
document.body.style.pointerEvents = ""
}}
>
{'Add Material'}
</DropdownMenuItem>
<DropdownMenuSeparator />
</DropdownMenuContent>
</DropdownMenu>
<AddGroupDialogContent />
</Dialog>
<Sheet open={openSheet} onOpenChange={setOpenSheet}>
<SheetTrigger>
<Button>{'Open'}</Button>
</SheetTrigger>
<AddItemSheetContent type={itemType} />
</Sheet>
</div>
)
}
In my case it appears that when i open my sheet within a DropdownMenuItem and closing the sheet afterwards the pointer event on the body remains none my fix was using document.body.style.pointerEvents = ""
To add to prev answer: the consistent way is to modify the DialogPrimitive.Close
component. You have to do the setTimeout. It's not great, happy to make a PR to issue a fix but I'm not exactly sure what the better solution is @shadcn
<DialogPrimitive.Close
className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
onClick={() => {
// yes, you have to set a timeout
setTimeout(() => (document.body.style.pointerEvents = ""), 500);
}}
>
<X className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
Any update on this?
<DropdownMenu>
<DropdownMenuTrigger asChild={true}>
<Button variant="ghost" className="h-8 w-8 p-0">
<span className="sr-only">Open Menu</span>
<span className="h-4 w-4">
<MoreHorizontal />
</span> </Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<AlertDialog>
<AlertDialogTrigger asChild>
<DropdownMenuItem
className="bg-green-500 hover:bg-green-700 hover:text-white"
onSelect={(e) => e.preventDefault()}
>
<Eye className="w-4 h-4 mr-2" /> Show Detail
</DropdownMenuItem>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
Are you sure?
</AlertDialogTitle>
<AlertDialogDescription>
Hahahahaha
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<DropdownMenuItem className="bg-yellow-500 hover:bg-yellow-700 hover:text-white">
<Pencil className="w-4 h-4 mr-2" /> Edit
</DropdownMenuItem>
<DropdownMenuItem className="bg-red-500 text-white hover:bg-red-700">
<Trash className="w-4 h-4 mr-2" /> Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu >
if you still have this problem, you can try using this code, i manage to open alert dialog inside the dropdown menu
This trick worked.
https://github.com/radix-ui/primitives/issues/1836#issuecomment-1674338372
you may also want to disable the modal of DropdownMenu by setting the value to false.
If it helps anyone, ran into the same problem and inspired by the comments above I solved it using this:
<AlertDialog
open={deleteDialogOpen}
onOpenChange={() => { setTimeout(() => (document.body.style.pointerEvents = ""), 100) }}
>
Seems to be working well so for now.
In my case l've got that error because on my dialog component I've imported by error this line of code import { DialogDescription } from '@radix-ui/react-dialog'
instead of import { DialogDescription } from './ui/dialog'
. Once I've changed it back it works as it should.
Thanks for the updates @braian-bernatto
Setting <DropdownMenu modal={false}>
solved the problem bcs i had two modal in place.
If it helps anyone, ran into the same problem and inspired by the comments above I solved it using this:
<AlertDialog open={deleteDialogOpen} onOpenChange={() => { setTimeout(() => (document.body.style.pointerEvents = ""), 100) }} >
Seems to be working well so for now.
Thanks @Kiranism ! I was using a Dropdown with a Button trigger. DropdownItems was opening a modal. After closing that modal anything was not clickable anymore. Setting modal={false}
solved the issue.
here's what i found to solve:
- update
@radix-ui/react-dropdown-menu
to2.1.1
- set
modal={false}
onDropdownMenu
hope it helps.
Thanks @dalalRohit! Solved the modal and dropdown menu problem :) Another problem I was having was when using a Popover inside the modal inside the dropdownmenu, which I also managed to solve by putting modal={true}
in the Popover.
here's what i found to solve:
- update
@radix-ui/react-dropdown-menu
to2.1.1
- set
modal={false}
onDropdownMenu
hope it helps.
only second option worked on me, thanks @dalalRohit
if you are using any popover/alertdialog/modal inside dropdown-menu set the modal=false on DropdownMenu fixes this issue
<DropdownMenu modal={false}>