primitives icon indicating copy to clipboard operation
primitives copied to clipboard

[bug]: Dialog leaves "pointer-events: none" on body after closing

Open devmahmoudi opened this issue 7 months ago • 11 comments

When using dialog/alert components in the application:

Opening a dialog adds `pointer-events: none` to the <body> tag (expected behavior)

Bug: After closing the dialog, the style persists (unexpected behavior)

Impact:

Users cannot interact with the page

Page appears to hang/freeze

Requires manual refresh to restore functionality

devmahmoudi avatar Aug 02 '25 13:08 devmahmoudi

The pointer-events: none style should be automatically removed when the dialog closes.

devmahmoudi avatar Aug 02 '25 13:08 devmahmoudi

+1, running into the same issue when using Dialog from @radix-ui/[email protected]

chris-ldgk avatar Aug 20 '25 21:08 chris-ldgk

Hitting the same problem here with latest version (1.1.15): <body class="..." the "pointer-events:none;" style is left on the

element after the dialog closes - curiously, it is not evident while the dialog is open. The problem only seems to occur if the Dialog does not use DialogTrigger and the open state is maintained by the application with const [open, setOpen] = useState(false) and <Dialog open={open} onOpenChange={setOpen}> (sorry, that's ShadCN markup, which uses @radix-ui/react-dialog under the covers).

The bug disables all pointer interactions and necessitates a browser page refresh to restore application functionality.

demonfiddler avatar Aug 28 '25 15:08 demonfiddler

After some more investigation, my hunch is that the effect within Dialog that makes sure to remove "pointer-events: none" from the body element does not get fired when controlling the open state from the outside.

My workaround was a useEffect like this:

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

useEffect(() => {
    if (open) return;
    // The setTimeout is necessary because otherwise it might fire before the component is closed
    setTimeout(() => {
         document.body.style.pointerEvents = "auto";
    }, 1);
}, [open])

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

chris-ldgk avatar Aug 28 '25 15:08 chris-ldgk

After some more investigation, my hunch is that the effect within Dialog that makes sure to remove "pointer-events: none" from the body element does not get fired when controlling the open state from the outside.

My workaround was a useEffect like this: ...

Thanks for the response @chris-ldg. I agree with your analysis and had in fact implemented a similar workaround myself.

demonfiddler avatar Aug 28 '25 19:08 demonfiddler

Possible duplicate of #3317 and #3445.

markuslewin avatar Sep 04 '25 17:09 markuslewin

After some more investigation, my hunch is that the effect within Dialog that makes sure to remove "pointer-events: none" from the body element does not get fired when controlling the open state from the outside.

My workaround was a useEffect like this:

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

useEffect(() => { if (open) return; // The setTimeout is necessary because otherwise it might fire before the component is closed setTimeout(() => { document.body.style.pointerEvents = "auto"; }, 1); }, [open])

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

@chris-ldgk Ugly. But it does the job for now. Thank you

Hoping for a fix soon from Radix

thebiltheory avatar Sep 06 '25 17:09 thebiltheory

@thebiltheory @devmahmoudi

I am using Shadcn, but the following solution should work for those too who are not using it.

Downloaded the radix-ui package:

yarn add radix-ui

And then import just the Dialog from it:

import { Dialog as DialogPrimitive } from "radix-ui";

Also, you might need to import the Alert from the radix-ui package as well. As the same issue with dialogs is present in alerts as well, since they use the same primitive (afaik).

Fixed it for me.

Fanoflix avatar Sep 08 '25 13:09 Fanoflix

I experienced a similar issue with the shadcn dialog component. I "fixed" by reverting to the previous version:

npm install @radix-ui/[email protected] 

gideonadeti avatar Sep 16 '25 19:09 gideonadeti

Unfortunately I am still going through the same issue, no matter the version. My current workaround was cleaning up event pointers: none after closing the dialog, which is far from ideal.

pauladiniz avatar Oct 08 '25 12:10 pauladiniz

A one-liner stop-gap fix (you'd need to remember to use it everywhere though) https://github.com/shadcn-ui/ui/issues/1912#issuecomment-1810037351

jnelken avatar Dec 02 '25 16:12 jnelken