reflex icon indicating copy to clipboard operation
reflex copied to clipboard

Page freezes and cannot do anything on page

Open alisaycl96 opened this issue 1 year ago β€’ 1 comments

Describe the bug We have a drawer with input text box to update a value show on page. When user click an update button in drawer, it'll call an alert dialog to ask user to confirm the updated information. If user click yes, then the data will be updated and show on page. However, after the drawer and alert dialog is closed, the page freezes and we cannot click anything without refreshing page. Same issue happens when change drawer into a dialog. This bug occurs when updating reflex to v0.6.6. Before v0.6.6, the page won't freeze.

We check in developer tool, it seems that on body, the style property pointer-events is still set to none after drawer and alert dialog are closed. It seems to be the root cause.

To Reproduce Steps to reproduce the behavior:

import reflex as rx


class State(rx.State):
    """The app state."""
    is_open: bool = False
    is_show_alert: bool = False
    text: str = ""
    input_str: str = ""

    @rx.event
    def open_drawer(self):
        self.is_open = True

    @rx.event
    def close_drawer(self):
        self.is_open = False

    @rx.event
    def open_confirm_alert(self):
        self.is_show_alert = True

    @rx.event
    def close_confirm_alert(self):
        self.is_show_alert = False

    @rx.event
    def update_text(self):
        self.close_drawer()
        self.close_confirm_alert()
        self.text = self.input_str


def drawer_content():
    return rx.drawer.content(
        rx.flex(
            rx.drawer.close(
                rx.button(
                    "Close",
                    on_click=State.close_drawer,
                )
            ),
            rx.hstack(
                rx.input(
                    on_blur=State.set_input_str,
                ),
                rx.button(
                    "Save",
                    on_click=State.open_confirm_alert,
                ),
            ),
            align_items="start",
            direction="column",
        ),
        height="100%",
        width="20%",
        padding="2em",
        background_color=rx.color("grass", 7),
    )


def lateral_menu():
    return rx.drawer.root(
        rx.drawer.trigger(
            rx.button(
                "Open Drawer",
                on_click=State.open_drawer,
            )
        ),
        rx.drawer.overlay(),
        rx.drawer.portal(drawer_content()),
        open=State.is_open,
        direction="left",
    )


def confirm_alert(yes_event, no_event, show_alert):
    return rx.alert_dialog.root(
        rx.alert_dialog.content(
            rx.alert_dialog.title("Confirm alert"),
            rx.alert_dialog.description(
                "Are you sure to update text?",
            ),
            rx.flex(
                rx.alert_dialog.action(
                    rx.button("Yes",
                              on_click=yes_event),
                ),
                rx.alert_dialog.cancel(
                    rx.button("Cancel",
                              on_click=no_event),
                ),
                spacing="3",
            ),
        ),
        open=show_alert,
    )


def index() -> rx.Component:
    return rx.container(
        rx.color_mode.button(position="top-right"),
        rx.vstack(
            rx.heading(State.text),
            lateral_menu(),
            confirm_alert(
                yes_event=State.update_text,
                no_event=State.close_confirm_alert,
                show_alert=State.is_show_alert,
            ),
            spacing="5",
            justify="center",
            min_height="85vh",
        ),
        rx.logo(),
    )


app = rx.App()
app.add_page(index)

Expected behavior Page should not freeze.

Screenshots ζˆͺεœ– 2024-12-13 上午12 46 08

Specifics (please complete the following information):

  • Python Version: v3.11.10
  • Reflex Version: v0.6.6
  • OS: MacOS
  • Browser (Optional): chrome

alisaycl96 avatar Dec 12 '24 16:12 alisaycl96

This appears to be caused by a bug in the frontend library that reflex uses, @radix-ui/themes, that is exposed in the Vaul drawer when used with modal=False and controlled open: https://github.com/emilkowalski/vaul/issues/492

The problem you're seeing is fixed in the upstream v3.1.6. However in reflex v0.6.5 we pinned @radix-ui/themes to <3.1.5 because they introduced 2 regressions: one in scroll area width and one in dialog flickering on close. Until those bugs are fixed, reflex is stuck on the older versions of @radix-ui/themes.

So what can be done to workaround?

--- repro_page_freeze/repro_page_freeze.py.orig	2024-12-13 14:56:51
+++ repro_page_freeze/repro_page_freeze.py	2024-12-13 16:10:32
@@ -1,5 +1,9 @@
 import reflex as rx
 
+fix_pointer_events_hack = rx.Var(
+    "(open) => {!open && window.setTimeout(() => (document.body.style.pointerEvents = 'auto'), 200)}",
+    _var_type=rx.EventChain,
+)
 
 class State(rx.State):
     """The app state."""
\ No newline at end of file
@@ -94,6 +98,7 @@
             ),
         ),
         open=show_alert,
+        on_open_change=fix_pointer_events_hack,
     )

We can use a bit of javascript to reset the CSS after some delay 🀷 it's not pretty, but it's possible.

Hopefully we'll be able to update our @radix-ui/themes package soon and then the hack can also go away.

masenf avatar Dec 14 '24 00:12 masenf

Fixed in 0.7.1 now that @radix-ui/themes has been bumped to >3.2.0

masenf avatar Mar 04 '25 19:03 masenf