-
Notifications
You must be signed in to change notification settings - Fork 30
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
CSS Variables For Dark Mode #4241
Comments
Do you think this proposal could be made to work with |
The mechanism itself would work with either yes. I'm hoping they'll eventually be the same thing, but it's definitely possible to add a bunch of dark mode stuff to
I think the existence of globals is inherent to how this works? You'll be swapping the value that a CSS var points to at a global level, depending on the user's preference.
I think this may be what I was referring to when I mentioned importing the variable strings instead of inlining the var names? So you could have an extra level where you have an object something like: const text = {
headline: '--var(text-headline)',
standfirst: '--var(text-standfirst)',
} And import/use that at the component level. That would guarantee that you always use a colour that's defined. |
I think we're saying the same thing 😄 So yes, technically a css variable is global but I was thinking if we keep their use limited to only the 'palette' file(s) then it's a sort of controlled global. We could perhaps enforce this with linting. So, as you say, instead of const text = {
headline: ${neutral[0]},
standfirst: ${neutral[46]},
} have const text = {
headline: '--var(text-headline)',
standfirst: '--var(text-standfirst)',
} At this point it's a question of tokenisation. You could put the abstraction at different places (we could map the Source api to replace each value with a css var) or define more descriptive colours locally. Eventually, I can imagine this sort of thing should be lifted into Source. I think the key is to not require any changes to the component code. This already uses |
👍
I think the difficulty I see with using Source colours (e.g. If we put Source colours into CSS variables I'm less clear about how you'd swap to the dark mode variants 🤔. |
I would be for using tokens from One issue that is not addressed here is what would be the |
This is the approach we’ve taken in #9181 |
A rough proposal for using CSS variables to power dark mode. There's lots of prior art on this topic here: guardian/source#1060 - many/most of the ideas in here come from @oliverlloyd @SiAdcock @mxdvl and @iainjchambers-guardian.
Overview
Editorial Palette
The editorial palette already provides a framework for selecting semantic light and dark mode colours for a given piece of UI. Here's a simplified example of what the
text
API looks like:CSS Variables
What if we were to leverage this to provide a group of CSS variables for each colour mode?
Note: This is for demo purposes, we may be able to reduce the boilerplate.
Components
Then in our components:
Note: Again this is for demo purposes, we may want to import these variable strings, instead of entering them manually in each place, for type safety. Or maybe that's overkill and this is fine.
Switching Modes
Now we simply activate either
lightPalette
ordarkPalette
at the top level of our app to have everything switch over automatically. We could do this via a media query (most likely option in apps):Or via other mechanisms, like JS or a
<link>
tag (more likely in dotcom):Storybook
There's currently a gap in our visual regression testing in Storybook: we're not testing dark mode. This is largely because our current dark mode implementation depends on the dark mode media query. The preference that powers this query can't be changed using the browser APIs, so we're stuck in light mode in storybook/Chromatic.
Switching to CSS variables would allow us to trigger light and dark mode simply by loading one of the two palettes of variables. We could configure one story to load the light palette and another to load the dark palette, thus getting around our existing problem.
Shared Components
Currently we have a need for shared components to only support dark mode some of the time, i.e. in some scenarios we can't have them provide dark mode styles even when the user is in dark mode. For
common-rendering
this will be the case for as long as dotcom doesn't support dark mode. For Source this may always be the case, as there may be some products that never support dark mode.At the moment we're relying on a
supportsDarkMode
prop to tell components incommon-rendering
whether to include their dark mode styles. We've discussed also using this pattern in Source.With the CSS variables approach this may no longer be necessary, as the components themselves may not need to worry about explicitly setting dark mode styles themselves. For
common-rendering
we can use the mechanism demonstrated in the Components section above; the nice thing about this is that it automatically works while dotcom doesn't support dark mode, because on that platform the variable will never be set to its dark variant. For Source we could do something like this (Source'sContainer
component):Advantages & Disadvantages
Advantages
common-rendering
and Source (no need for thesupportsDarkMode
prop, or built-in dark mode styles)Disadvantages
The text was updated successfully, but these errors were encountered: