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: add support for system color scheme #3167

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

Conversation

chrisgzf
Copy link
Member

@chrisgzf chrisgzf commented Jan 16, 2021

Context

Very WIP, just the preliminary implementation first. PRing for sanity check.

Based on #1289.

Implementation

Roughly:

  • Uses matchMedia to check for prefers-color-scheme media query
  • Adds a third default option to the mode selector
  • When it is set to default, AppShell checks for OS dark mode preference, and applies dark mode if there is dark mode preference
  • Whenever the user is in Default mode and presses x to toggle their mode, they have made a conscious choice to switch away from the Default, and it will be set to Light/Dark accordingly

Todo

  • Make it work with export service
  • Write tests

Note:
The keyboard toggling and setting of dark mode feels a bit laggy in dev, but isn't sluggish once exported. There is also incorrect snackbar notification text, which will be fixed in #3165.

Picture:
image

GIF:
ezgif-7-77d0500e1ca8

@vercel
Copy link

vercel bot commented Jan 16, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployments, click below or on the icon next to each commit.

nusmods-website – ./website

🔍 Inspect: https://vercel.com/nusmodifications/nusmods-website/ah4qvt0h1
✅ Preview: https://nusmods-website-git-fork-chrisgzf-os-default-night-dark-mode.nusmodifications.vercel.app

nusmods-export – ./export

🔍 Inspect: https://vercel.com/nusmodifications/nusmods-export/n688dqiii
✅ Preview: https://nusmods-export-git-fork-chrisgzf-os-default-night-dark-mode.nusmodifications.vercel.app

Copy link
Member

@taneliang taneliang left a comment

Choose a reason for hiding this comment

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

This looks like it won't automatically update when the browser changes mode. Plus, having a reducer read data from outside feels like a violation of FP principles as the reducer is no longer pure.

Maybe we should implement this a different way. The Redux store should go back to being a store of the user's setting. We can do the theme switching in a new useIsDarkMode hook similar to this useBrowserTheme hook, which can read from the user's setting and listen to changes to the browser's dark mode. This can be easily done using our existing useMediaQuery hook.

AppShell can then just do const isDarkMode = useIsDarkMode().

export type Mode = 'LIGHT' | 'DARK';
export type Mode = 'DEFAULT' | 'LIGHT' | 'DARK';

export const DEFAULT_MODE: Mode = 'DEFAULT';
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, is there a better name for this variable? "Default mode" doesn't mean much out of context hahaha. I can't think of anything though

Copy link
Member Author

Choose a reason for hiding this comment

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

What about DEFAULT_DISPLAY_MODE? Or OS_DEFAULT_DISPLAY_MODE? Was actually thinking of refactoring all the Mode names to DisplayMode, i.e. LIGHT_DISPLAY_MODE or DARK_DISPLAY_MODE etc, so that it sounds less generic.

Copy link
Member

Choose a reason for hiding this comment

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

DisplayMode also sounds a bit vague though. I've looked up a bunch of potential alternatives:

Unfortunately most of them also sound vague. Some also sound similar to our existing Theme, which I guess is fine as I blame Theme for being even more vague -- we should probably rename or remove it instead.

I think DarkColorPreference is the clearest, as this var and type will only be used to store the user's preference. The useIsDarkMode hook can return a boolean based on the preference + the CSS media query.

Copy link
Member

Choose a reason for hiding this comment

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

See global PR comment for what I've done to resolve this.

@chrisgzf
Copy link
Member Author

@taneliang Thanks for the review and sanity check! Agree on the reducer reading data from the outside being pretty iffy! I kinda know how to move on from here with your suggestions. I will slowly work on this over the next week.

@taneliang
Copy link
Member

Btw we'll also need to display the segmented control better on xs 😆

image

@ravern
Copy link
Member

ravern commented Mar 27, 2024

I think if we just change the label to "Auto" (which is still telling) it looks fine.

image

This is on iPhone SE.

Copy link

vercel bot commented Apr 3, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
nusmods-export ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 21, 2024 1:13pm
nusmods-website ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 21, 2024 1:13pm

Copy link

vercel bot commented Apr 3, 2024

@ravern is attempting to deploy a commit to a Personal Account owned by @nusmodifications on Vercel.

@nusmodifications first needs to authorize it.

@ravern ravern changed the title [WIP] Add support for OS default dark mode feat: add support for system color scheme Apr 3, 2024
@ravern ravern force-pushed the os-default-night-dark-mode branch from dc49895 to d824b9b Compare April 3, 2024 08:36
@ravern
Copy link
Member

ravern commented Apr 3, 2024

I've rebased this onto the latest master and made some changes to how the "auto" light/dark mode works, taking into account @taneliang's comments too.

Mode is now split into two different concepts: ColorScheme and ColorSchemePreference.

  • ColorSchemePreference is the user-selected preference in the settings. It is either "auto", "light" or "dark".
  • ColorScheme is the final decided color scheme. It is either "light" or "dark".

The useColorScheme hook transforms the ColorSchemePreference stored in the Redux store into a ColorScheme, which is used to determine if we'll render light or dark mode palette. Should the user preference be set to "auto", I used a useMediaQuery hook to determine the system-preferred color scheme and return "light" or "dark" accordingly.

There was an issue where the behaviour of a toggleMode/toggleColorScheme action is now unclear — how do we toggle an "auto" preference if we don't have access to the external state i.e. the media query? To resolve this, I removed the action entirely, and changed the only dispatcher of this action — the 'x' keybinding handler — to use a combination of useColorScheme and setColorScheme instead. I also removed the corresponding tests.

Finally, regarding export, I refactored the export component to be a functional component instead, giving me access to useColorScheme, which I then used to determine the color scheme of the rendered output.

Copy link

codecov bot commented Apr 3, 2024

Codecov Report

Attention: Patch coverage is 56.16438% with 32 lines in your changes are missing coverage. Please review.

Project coverage is 53.53%. Comparing base (c26ef0b) to head (55da21f).

Files Patch % Lines
website/src/utils/colorScheme.ts 35.71% 9 Missing ⚠️
website/src/views/timetable/ExportMenu.tsx 69.56% 7 Missing ⚠️
website/src/views/hooks/useColorScheme.tsx 54.54% 5 Missing ⚠️
website/src/views/components/KeyboardShortcuts.tsx 0.00% 4 Missing ⚠️
website/src/views/AppShell.tsx 0.00% 2 Missing ⚠️
website/src/views/settings/ModeSelect.tsx 0.00% 2 Missing ⚠️
website/src/apis/export.ts 66.66% 1 Missing ⚠️
website/src/entry/export/main.tsx 0.00% 1 Missing ⚠️
...ite/src/views/components/disqus/DisqusComments.tsx 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3167      +/-   ##
==========================================
- Coverage   53.59%   53.53%   -0.06%     
==========================================
  Files         272      274       +2     
  Lines        5988     6017      +29     
  Branches     1434     1443       +9     
==========================================
+ Hits         3209     3221      +12     
- Misses       2779     2796      +17     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Member

@kokrui kokrui left a comment

Choose a reason for hiding this comment

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

LGTM and works on my machine! a few nits but overall ready to merge. good stuff!

export const DARK_MODE: Mode = 'DARK';
/**
* Color schemes simply define whether the website is in light or dark mode. This
* is not to be confused with themese, which define the color palette of the website.
Copy link
Member

Choose a reason for hiding this comment

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

nit: themese -> themes

export type Theme = {
readonly id: ThemeId;
readonly name: string;
};

export type Mode = 'LIGHT' | 'DARK';
Copy link
Member

Choose a reason for hiding this comment

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

wow this is a much-needed refactoring LOL good stuff

@@ -114,7 +114,7 @@ const SettingsContainer: React.FC<Props> = ({
</p>
Copy link
Member

Choose a reason for hiding this comment

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

it might be good to add the fact that "Auto" uses your system preferences in this protip here^

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.

None yet

4 participants