Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dark Mode Toggle Not Working in 0.6.6 - Regression from 0.6.5 #4464

Open
ebonura-fastly opened this issue Dec 3, 2024 · 15 comments · May be fixed by #4467
Open

Dark Mode Toggle Not Working in 0.6.6 - Regression from 0.6.5 #4464

ebonura-fastly opened this issue Dec 3, 2024 · 15 comments · May be fixed by #4467
Assignees
Labels
bug Something isn't working

Comments

@ebonura-fastly
Copy link

Describe the bug
The dark mode toggle functionality from the official Reflex documentation breaks in version 0.6.6. The same example works correctly in version 0.6.5.

To Reproduce
Steps to reproduce the behavior:

  1. Use the example code from https://reflex.dev/docs/recipes/others/dark-mode-toggle/
  2. Run the code with Reflex 0.6.6
  3. Attempt to toggle dark mode
  4. Toggle fails to function as expected

Code/Link to Repo: Using official documentation example from https://reflex.dev/docs/recipes/others/dark-mode-toggle/

Expected behavior
Dark mode toggle should switch between light and dark themes as demonstrated in the documentation and as functioning in Reflex 0.6.5.

Specifics

  • Python Version: 3.12
  • Reflex Version: 0.6.6 (broken), 0.6.5 (working)
  • OS: MacOS
  • Browser: Tested in Chrome and Safari

Additional context
The issue appears to be a regression as the official documentation example functions correctly in version 0.6.5 but breaks in 0.6.6. The bug is reproducible across different browsers.

Copy link

linear bot commented Dec 3, 2024

@Lendemor Lendemor added the bug Something isn't working label Dec 3, 2024
@Lendemor
Copy link
Collaborator

Lendemor commented Dec 3, 2024

Tested locally.
I can reproduce the problem.

After further checking, it seems like the theme value is set correctly (see DevTools > Application > Local Storage > theme), but is somehow ignored.

@Lendemor
Copy link
Collaborator

Lendemor commented Dec 3, 2024

@ebonura-fastly
Hum, I've been doing more testing but it's not happening anymore despite not changing anything in the code.
Can you try running reflex init again maybe on your project and tell me if it keep happening?

edit: Managed to make it happens again.

@Lendemor Lendemor linked a pull request Dec 3, 2024 that will close this issue
@Lendemor
Copy link
Collaborator

Lendemor commented Dec 3, 2024

So overall it's a pretty weird issue.

Here is a list of a few things I tried (all on the latest commit of main):

  • Open the page in Safari: ✅
  • Open the page in Chrome Incognito: ✅
  • Refresh existing tab for the page: ✅
  • Sometimes the toggle fail on the existing page, but it works again after refresh of the page.

I added an integration tests that should be pretty exhaustive to catch those issues, and it seems to be passing, but I can't explain why it sometimes happens like that.

@Lendemor
Copy link
Collaborator

Lendemor commented Dec 3, 2024

After more testing, it seems like a page refresh seems to trigger the bug consistently.

  1. Open the page
  2. Go to light mode (when it's working)
  3. Do a page reload.
  4. Page is in dark mode even though all the variable are set to light.

Once the color mode is broken, it stay broken even with refresh.

However, if you do:

  1. Switch back to color_mode dark.
  2. Refresh the page.
  3. Switch to color_mode light.
  4. The page is in light mode again.

I ran the test above on multiple browser:
Google Chrome ❌
Google Chrome Incognito ✅
Safari ✅
Firefox ✅

@Lendemor
Copy link
Collaborator

Lendemor commented Dec 3, 2024

I added a page reload in the test above to try and catch the issue, but it doesn't, at least locally.

I suspect some browser specific issue.

@Lendemor
Copy link
Collaborator

Lendemor commented Dec 3, 2024

While inspecting the page, I've noticed that the attributes dark-native-active show up in the <html> tag of the page, which seems to supersede the actual color mode management in reflex.

@ebonura-fastly do you also see this attribute ?

@Seikened
Copy link

Seikened commented Dec 5, 2024

Captura de pantalla 2024-12-05 a la(s) 12 26 30 a m

Do you mean of this?

@ebonura-fastly
Copy link
Author

Thanks for checking this, @Lendemor . When switching between dark/light modes, the HTML tag only switches between:

class="light" style="color-scheme: light"

or

class="dark" style="color-scheme: dark"

I've tested this across multiple versions (0.6.5, 0.6.6, and 0.6.6.post2) on both Chrome and Safari, and don't see the dark-native-active attribute you mentioned.

I've also tried running reflex init and refreshing the page multiple times, but the issue persists

@Lendemor
Copy link
Collaborator

Lendemor commented Dec 5, 2024

image
This show up for me if I refresh while in light mode.
Which seems to override the page and make it render in dark mode despite the other attribute being set to light.
This is the only case where I reproduced the issue.

Edit: I found the extension in my browser that was messing with the page and adding that attribute. Once I turned it off, I don't reproduce that issue anymore 🤔

@ebonura-fastly
Copy link
Author

@Lendemor I've double-checked the issue with Chrome incognito and Safari (no extensions installed) - it persists in both. While I do use Dark Reader, the problem seems to occur even with all extensions disabled.

@Lendemor
Copy link
Collaborator

Lendemor commented Dec 5, 2024

Screen Recording 2024-12-05 at 14 57 58

I'm running out of idea on what to test / how to find the problem.

This is the app I'm using to test :

import reflex as rx
from reflex.style import set_color_mode, color_mode, resolved_color_mode

app = rx.App()


@app.add_page
def index():
    return (
        rx.segmented_control.root(
            rx.segmented_control.item(
                rx.icon(tag="monitor", size=20),
                value="system",
            ),
            rx.segmented_control.item(
                rx.icon(tag="sun", size=20),
                value="light",
            ),
            rx.segmented_control.item(
                rx.icon(tag="moon", size=20),
                value="dark",
            ),
            on_change=set_color_mode,
            variant="classic",
            radius="large",
            value=color_mode,
        ),
        rx.text(rx.constants.Reflex.VERSION),
        # rx.color_mode.button(allow_system=True),
        rx.text(color_mode, id="current_color_mode"),
        rx.text(resolved_color_mode, id="resolved_color_mode"),
        rx.text(rx.color_mode_cond("LightMode", "DarkMode"), id="color_mode_cond"),
    )

@ebonura-fastly
Copy link
Author

Hey @Lendemor I think I found the root cause, it is related to the appearance setting in rx.theme, which in 0.6.6 will override whatever is set in the segmented control, this was not happening in previous versions.

The reason why I couldn't switch is because I had the appearance set to light in my rx.theme to provide a default.

Thanks for your help and patience while we debugged this! I think the issue can be closed, I'll leave it to you and your team if this is the expected behavior, I do believe it should be noted in https://reflex.dev/docs/recipes/others/dark-mode-toggle/ though, just to avoid confusion as people may not have it working as expected

For reference, here's a minimal example showing the difference:

import reflex as rx
from reflex.style import set_color_mode, color_mode, resolved_color_mode

def example_theme(appearance: str = None):
    return rx.theme(
        appearance=appearance
    )

def dark_mode_toggle():
    return rx.segmented_control.root(
        rx.segmented_control.item(rx.icon(tag="monitor", size=20), value="system"),
        rx.segmented_control.item(rx.icon(tag="sun", size=20), value="light"),
        rx.segmented_control.item(rx.icon(tag="moon", size=20), value="dark"),
        on_change=set_color_mode,
        variant="classic",
        radius="large",
        value=color_mode,
    )

def index():
    return rx.vstack(
        rx.heading("Dark Mode Demo"),
        dark_mode_toggle(),
        rx.text("Current mode: ", color_mode),
        rx.text("Resolved mode: ", resolved_color_mode),
        rx.text(rx.color_mode_cond("Light Theme", "Dark Theme")),
    )

# Comment/uncomment to see difference
# app = rx.App(theme=example_theme("light"))
app = rx.App(theme=example_theme())

app.add_page(index)

@Lendemor
Copy link
Collaborator

Lendemor commented Dec 6, 2024

Hi @ebonura-fastly, thanks for figuring that out.

Imo it's definitely a regression, the appearance should only be the default for how the page is supposed to be when first opened, not a fixed value.

I'm not sure how to fix that bug (yet) but I'll update the test to take this use-case into account.

@Lendemor
Copy link
Collaborator

Found a fix for this, added it in #4467

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants