Updated

2 min read

ShadCN/Radix Dropdown Open on Hover Tutorial (Fix "Flicker")

Ryan ChiangBy Ryan Chiang (@ryanscio)

Happy Sunday everyone!

Today I debugged an annoying UI bug when using shadcn / Radix UI's Dropdown Menu component.

The Bug

I wanted the dropdown menu on Featurable to open when hovering (my thinking was: why make the user do extra clicks?) and stay open while interacting with the dropdown.

My first attempt was to wrap the DropdownMenu in a <div>:

HeaderLink.tsx
const HeaderLink = () => { const [dropdownOpen, setDropdownOpen] = useState(false); return ( <div onMouseLeave={() => { // Close when leaving the trigger or dropdown menu setDropdownOpen(false); }} > <DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen} > <DropdownMenuTrigger onMouseEnter={() => setDropdownOpen(true)} > Open me! </DropdownMenuTrigger> <DropdownContent> {/* Dropdown content goes here */} </DropdownContent> </DropdownMenu> </div> ); }

This worked! But it caused an annoying flicker:

If you were to console.log the mouseenter and mouseleave events, you'd see:

Entering Leaving Entering

So why was this happening?

After debugging, I noticed that upon opening the Dropdown Menu, Radix UI was causing the body tag to receive style="pointer-events: none", which prevented scrolling and any outside interaction while the dropdown was open.

Here's what was happening:

  1. Hover the trigger --> mouseenter event (1st Entering console log)
  2. Dropdown opens
  3. Body receives pointer-events: none
  4. Since the trigger (which is in the <body>) can not receive mouse events, it fires a mouseleave (Leaving console log)

The Fix

The fix is actually quite simple. Simply add modal={false} to the DropdownMenu component like so:

const HeaderLink = () => { const [dropdownOpen, setDropdownOpen] = useState(false); return ( <div onMouseLeave={() => { // Close when leaving the trigger or dropdown menu setDropdownOpen(false); }} > <DropdownMenu open={dropdownOpen} onOpenChange={setDropdownOpen} modal={false} // This will prevent the dropdown menu from being a modal > <DropdownMenuTrigger onMouseEnter={() => setDropdownOpen(true)} > Open me! </DropdownMenuTrigger> <DropdownContent> {/* Dropdown content goes here */} </DropdownContent> </DropdownMenu> </div> ); }

Now when the DropdownMenuTrigger is hovered, the <body> tag will not receive pointer-events: none.

Let's see the fix in action:

It worked! Hope this quick fix helps you with this annoying UI bug when using shadcn or Radix UI.

Ryan Chiang

Meet the Author

Ryan Chiang

Hey! I'm Ryan. I build things and write about them. This is my blog of my learnings, tutorials, and whatever else I feel like writing about.
What I'm currently building →.

2026

2025

2024

2023

?