Using shadcn/ui
's Sheet
along with a DropdownMenu
in the Sheet
.
When the dropdown trigger button is clicked it gives the following error in the console
Blocked aria-hidden on an element because its descendant retained focus. The focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at .
Element with focus: div
Ancestor with aria-hidden:
The code for the same is
return (
<>
<Sheet open={isOpen} onOpenChange={(open) => !open && onClose()}>
<SheetContent onOpenAutoFocus={(e) => e.preventDefault()} className="p-0 overflow-auto">
<SheetHeader>
<VisuallyHidden><SheetTitle>Person Detail</SheetTitle></VisuallyHidden>
<div className="grid gap-4 p-6">
<div className="flex items-center justify-between mt-2">
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center">
<EllipsisVertical />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={editPerson} className="cursor-pointer">
<UserPen />
Edit Person
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className="text-red-800 cursor-pointer" onClick={deletePersonAction}>
<Trash2 />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<hr className="h-px my-2 bg-gray-200 border-0 dark:bg-gray-700"/>
</div>
</SheetHeader>
<div className="grid gap-4">
<!-- other content here -->
</div>
</SheetContent>
</Sheet>
</>
);
Using shadcn/ui
's Sheet
along with a DropdownMenu
in the Sheet
.
When the dropdown trigger button is clicked it gives the following error in the console
Blocked aria-hidden on an element because its descendant retained focus. The focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus. For more details, see the aria-hidden section of the WAI-ARIA specification at https://w3c.github.io/aria/#aria-hidden.
Element with focus: div
Ancestor with aria-hidden:
The code for the same is
return (
<>
<Sheet open={isOpen} onOpenChange={(open) => !open && onClose()}>
<SheetContent onOpenAutoFocus={(e) => e.preventDefault()} className="p-0 overflow-auto">
<SheetHeader>
<VisuallyHidden><SheetTitle>Person Detail</SheetTitle></VisuallyHidden>
<div className="grid gap-4 p-6">
<div className="flex items-center justify-between mt-2">
<DropdownMenu>
<DropdownMenuTrigger className="flex items-center">
<EllipsisVertical />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={editPerson} className="cursor-pointer">
<UserPen />
Edit Person
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className="text-red-800 cursor-pointer" onClick={deletePersonAction}>
<Trash2 />
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<hr className="h-px my-2 bg-gray-200 border-0 dark:bg-gray-700"/>
</div>
</SheetHeader>
<div className="grid gap-4">
<!-- other content here -->
</div>
</SheetContent>
</Sheet>
</>
);
Share
Improve this question
asked Feb 7 at 14:43
Anuj TBEAnuj TBE
9,79034 gold badges146 silver badges304 bronze badges
1
- Can you give more details, like versions and so on? I'm not able to reproduce, perhaps one of your actions is retaining focus? Here's a sandbox with latest versions for shadcn components, replacing the actions with console logs: codesandbox.io/p/devbox/5lzsk8 – Janoma Commented 2 days ago
1 Answer
Reset to default 0I have the same issue with Dialog associated to Dropdown component.
Here is the error code I get in console :
Blocked aria-hidden on an element because its descendant retained focus. The focus must not be hidden from assistive technology users. Avoid using aria-hidden on a focused element or its ancestor. Consider using the inert attribute instead, which will also prevent focus
And I see in elements inspector than the body element receive this after closing Dialog :
style: "pointer-events: none;"
My code here :
const renderDialogContent = () => {
if(!action) return null;
const { value, label } = action
return (
<DialogContent className="shad-dialog button">
<DialogHeader className="flex flex-col gap-3">
<DialogTitle className="text-center text-light-100">{label}</DialogTitle>
{value === "rename" && (
<div className="flex flex-row">
<InputRenameLeft
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<InputRenameRight
type="text"
value={"."+file.extension}
disabled
className="!cursor-default !select-none"
/>
</div>
)}
{value === "details" && (
<FileDetails file={file} />
)}
{value === "share" && (
<ShareInput users={users} file={file} onInputChange={setEmails} onRemove={handleRemoveUser} isRemoving={isRemoving} id={id} isSubmitted={isLoading}/>
)}
{value === "delete" && (
<p className="delete-confirmation">
Are you sure to delete {` `}
<span className="delete-file-name">{file.name}</span> ?
</p>
)}
</DialogHeader>
{value === "share" && (
<DialogFooter className="flex flex-col gap-3 md:flex-row">
<Button onClick={closeAllModals} className="modal-cancel-button">
Cancel
</Button>
<Button onClick={handleAction} className="modal-submit-button" disabled={isLoading || emails.length === 0}>
<p className="capitalize">{value}</p>
{isLoading && (
<Image src="/assets/icons/loader-white.png" alt="loader" width={24} height={24} className="animate-spin"/>
)}
</Button>
</DialogFooter>
)}
{value === "rename" && (
<DialogFooter className="flex flex-col gap-3 md:flex-row">
<Button onClick={closeAllModals} className="modal-cancel-button">
Cancel
</Button>
<Button onClick={handleAction} className="modal-submit-button" disabled={isLoading || name === file.name.replace(`.${file.extension}`, '')}>
<p className="capitalize">{value}</p>
{isLoading && (
<Image src="/assets/icons/loader-white.png" alt="loader" width={24} height={24} className="animate-spin"/>
)}
</Button>
</DialogFooter>
)}
{value === "delete" && (
<DialogFooter className="flex flex-col gap-3 md:flex-row">
<Button onClick={closeAllModals} className="modal-cancel-button">
Cancel
</Button>
<Button onClick={handleAction} className="modal-submit-button" disabled={isLoading}>
<p className="capitalize">{value}</p>
{isLoading && (
<Image src="/assets/icons/loader-white.png" alt="loader" width={24} height={24} className="animate-spin"/>
)}
</Button>
</DialogFooter>
)}
</DialogContent>
)
}
return (
<Dialog open={isModalOpen} onOpenChange={(isOpen) => { setIsModalOpen(isOpen); if (!isOpen) closeAllModals(); }}>
<DropdownMenu open={isDropdownOpen} onOpenChange={setIsDropdownOpen}>
<DropdownMenuTrigger className="shad-no-focus transition-all duration-200 hover:text-brand"><IoEllipsisVertical /></DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel className="max-w-[200px] truncate">{file.name}</DropdownMenuLabel>
<DropdownMenuSeparator />
{actionsDropdownItems.map((actionItem) => (
<DropdownMenuItem key={actionItem.value} className="shad-dropdown-item" onClick={() => {
setAction(actionItem)
if(["rename", "share", "delete", "details"].includes(actionItem.value)) {setIsModalOpen(true)}
}}>
{actionItem.value === "download" ?
(<Link href={constructDownloadUrl(file.bucketFileId)} download={file.name} className="flex items-center gap-2">
<Image src={actionItem.icon} alt={actionItem.label} width={30} height={30}/>
{actionItem.label}
</Link>)
:
(
<div className="flex items-center gap-2">
<Image src={actionItem.icon} alt={actionItem.label} width={30} height={30}/>
{actionItem.label}
</div>
)
}
</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
{renderDialogContent()}
</Dialog>
)