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

feat: respect user's preferred color scheme (dark mode repair) #3102

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

jewhyena
Copy link

@jewhyena jewhyena commented Oct 9, 2024

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Docs
  • Other... Please describe:

What is the current behavior?

Currently, the Nest.js documentation site does not respect the user's system preferences regarding the color scheme (light or dark). As a result, opening the site in a new browser or in an Incognito session always defaults to light mode, ignoring the system preferences.

Manually toggling the theme will save the current theme in localStorage, so the next time the user opens the site, it will remain the same.

Issue Number: N/A

What is the new behavior?

The new behavior respects the user's system preferences. If their preferred color scheme is dark, the Nest.js site will default to dark mode, and similarly, if their preferred color scheme is light, it will be in light mode. It now also listens for changes in the preferred color scheme, and the Nest.js site will automatically change its theme according to the current system preferences.

If the user manually toggles the theme button, the theme will be stored in localStorage and remain there. In this case, the theme will not respect the system preferences. Instead, localStorage will be the source of truth.

Please see the attached video.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Screen.Recording.2024-10-10.at.12.34.30.AM.mov

@micalevisk
Copy link
Member

micalevisk commented Oct 13, 2024

I guess this isn't working on Ubuntu (firefox) 🤔 I tested the deploy preview

demo_linux.webm

@jewhyena
Copy link
Author

jewhyena commented Oct 14, 2024

I guess this isn't working on Ubuntu (firefox) 🤔 I tested the deploy preview

demo_linux.webm

Hm. That is strange. There's no platform-dependent code.

It works seamlessly on both Chrome and Firefox on my Mac, as well as on my iPhone.

By any chance, didn't you manually change the theme on the site before starting switching your system preference? Was your localStorage clear?

Because once you manually change the theme on the site, it no longer respects your system preference. After you click the button, the localStorage becomes the source of truth for the theme. Such behavior is expected.

@jewhyena jewhyena force-pushed the fix/respect-users-preferred-color-scheme branch from be12438 to 858a6e4 Compare October 14, 2024 19:58
@micalevisk
Copy link
Member

still not working here 🤔

demo2.webm

while the theme switching worked for discord desktop app

@jewhyena
Copy link
Author

jewhyena commented Oct 14, 2024

while the theme switching worked for discord desktop app

Hmm.

Since Discord is a different app which might not have any issues resolving the preferred schema on Ubuntu, let's check if it's the same with https://reactnative.dev/ and https://reactnavigation.org/ websites.

Could you please tell me whether those two sites respect your color scheme or do nothing as well?

@micalevisk
Copy link
Member

they didn't work on firefox neither

but I just found that everything went fine on chrome

@jewhyena
Copy link
Author

they didn't work on firefox neither

but I just found that everything went fine on chrome

Might be some issue with GNOME: https://askubuntu.com/a/1464951. 🤔

Comment on lines -22 to -26
// This is commented out because by default the theme mode is set to light (at least for now)
// const userPrefersTheme =
// this.mediaMatcher.matchMedia &&
// this.mediaMatcher.matchMedia('(prefers-color-scheme: light)').matches;
// this.setThemeMode(this.getUserSettingsIsDarkMode() || userPrefersTheme);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't just uncommenting this code be enough?

Copy link
Author

@jewhyena jewhyena Oct 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I originally hoped for, but it didn't seem to be working (video attached). So I started fixing it.

Screen.Recording.2024-10-17.at.11.53.16.AM.mov

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you certain there's nothing in your local storage that specifies which mode to use? If I remember correctly, the commented-out code checks local storage first and, if it's empty, falls back to the user's preferred color scheme.

Copy link
Author

@jewhyena jewhyena Oct 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you certain there's nothing in your local storage that specifies which mode to use?

Yes, absolutely. You can see in the video that my localStorage is empty.

Moreover, looking at the old code, it isn't even supposed to listen to any changes in color scheme preferences, since there is no onChange event listener specified anywhere. It only supposed to get the system preferences on the initial load (ngOnInit). But it turns out that it also doesn't work if we just uncomment the code. I get the light mode despite of my system preference being dark.

It might seem like the code on lines 28-29, which overrides everything returned by the mediaMatches, was put in there as a temporary substitution for the commented code. If we remove that and leave only uncommented code, it starts working but in the opposite direction: if my system preference is dark, it gives me the light mode; and, vice versa, if my system preference is light, only then it gives me the dark mode.

However, if we change the mediaMatcher query from (prefers-color-scheme: light) to (prefers-color-scheme: dark), it starts to give me the correct theme.

But it still does not listen to any changes in the system preferences. If you change your system preference manually, or if your OS configured to change the system preference automatically at different times of the day, you have to refresh your page in order for theme to change. This is what I intended to fix in this PR.

I added an event listener which—if there is no stored theme in localStorage—would automatically change the theme according to the system preference, without need to refresh the page. Also there is skipStorage parameter which allows skipping saving the theme in localStorage. We need this flag in order to prevent onChange event from storing anything in localStorage. Otherwise, once our system preference changes for the first time, the site will no longer respect it, despite the user not selecting the preferred theme manually by clicking the theme button. This is not the behavior we usually expect and I would consider it to be a bug.

What I'm not so sure about, though, is the use of changeDetectorRef. I don't know if this is a good or a bad practice, since this PR is basically the first time I ever touched Angular; so I would appreciate any advice on this.

The reason I have added this is that when the system preference change, the theme icon at the top right corner stays the same. You can notice it in the video I first attached to the PR. I recorded it before noticing it myself and before I pushed the fix.

For some reason, when theme change was caused by darkSchemeMatcher.onchange event, *ngIfs in the .html file didn't react to the change and stayed the same. So I found this approach with changeDetectorRef and with it all went as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants