Page MenuHomePhabricator

[Spike] Determine how to Codex should support different themes/modes
Closed, ResolvedPublic5 Estimated Story PointsSpike

Description

In a previous spike, DST engineers proposed a way that Codex could introduce some "experimental" support for CSS custom properties (see T353172) now, as the Web Team begins developing and beta-testing the reading preferences features.

The solution outlined in T353172 is suitable for the short-term, but we should also start thinking about a more long-term solution in terms of how Codex supports various forms of UI customization (color modes, font sizes, etc).

Questions
  • Should a new dark color palette live within the Codex Design Tokens project?
    • If so, where will it be defined?
    • If not, where should this information live?
  • What kind of themes or modes should Codex support? Dark mode, high contrast mode, variant font sizes?
    • What about completely re-skinned versions of the design system for use outside of WMF projects? Is this within scope or not?
  • Should Codex start making a greater reliance on CSS custom properties to enable changes between different themes/modes on the client side?
  • Do we need to reorganize any of our current token system to support these goals?
Proposal: 3-tiered system with CSS Variable output

I have a proposal that attempts to answer these questions, which exists as a proof-of-concept patch that can be found here. The basic idea is that all design tokens would be organized into three different tiers:

  1. Options tier: one big set of options representing the universe of possible values. We might add more over time but we're not really swapping them out. Variable names would be descriptive (color-blue.500). All of these tokens should have a primitive value; none should refer to other tokens.
  2. Application tier: One or more sets of theme/application/decision level tokens. Variables here would have semantic names (color primary, color destructive, etc), and would refer to option tokens for values. One of these files would be the default and would define all the tokens that get exported from Codex. Other files could override a subset of these tokens to support a specific "mode" (dark mode, high contrast, maybe also alternate font sizes, etc).
  3. Component-specific tokens. The values of these tokens would only reference the application tokens of level 2 (not the option tokens of level 1) so that component styles always respect the current theme or mode. Even a component like our "red links" may need a different shade of red for legibility against a dark background, so we shouldn't reference option tokens directly here.

Our system is already organized along similar lines, but this proposal aims to clarify that custom variants of Codex would be defined at the second tier, as overrides to default values (not as replacement of base-level option tokens). We might also need to move some of our tokens (like "accent color", which lives in our base level currently), and finally we'd want to ensure that no component-level tokens ever referenced low-level options. Adoption of this proposal would require few if any name changes for individual tokens (something we definitely want to minimize).

The final Codex styles would also be updated to include CSS variables in the final output for all application-level tokens (and maybe the component ones as well), but option-level tokens would continue to be omitted. Alternative modes could be defined as minimal stylesheets that would be loaded on top of the default styles, and would mostly consist of overrides to existing variables (inside a media query or nested under a particular selector). This solution would only target modern browsers that can support CSS custom properties, as well as CSS features like color-scheme.

Taken together, this would mean that a page could do something like this:

:root {
    color-scheme: dark light;
}

/* These media queries could be defined in conditionally loaded files */
@media (prefers-color-scheme: dark) {
  /* Dark mode styles here */
}

@media (prefers-color-scheme: light) {
  /* Light mode styles here */
}

/* user-controlled mode toggle would apply this class to the body or html element,
   forcing all descendants to use dark mode from the media query above */
.dark {
    color-scheme: dark;
}

This proposal is based on the "multi-file" strategy defined in this extensive blog post from Danny Banks, the creator of Style Dictionary (which we use to manage our tokens). Brad Frost's 2018 "Creating Themeable Design Systems" is also a good resource.

Acceptance Criteria
  • DST designers and engineers discuss and agree on a solution
  • A new ADR is added to the Codex docs site summarizing this solution

Any necessary code changes can be handled as separate follow-up tasks.

Event Timeline

CCiufo-WMF added a subscriber: DTorsani-WMF.
CCiufo-WMF changed the subtype of this task from "Task" to "Spike".Feb 5 2024, 6:55 PM
CCiufo-WMF set the point value for this task to 5.

Some thoughts...

Should a new dark color palette live within the Codex Design Tokens project?

Yes, absolutely. The colors and their application should be part of the design system.

What about completely re-skinned versions of the design system for use outside of WMF projects? Is this within scope or not?

I'm pretty convinced that we should not worry about this. Codex is the design system for Wikimedia, so I think it's okay to limit ourselves, especially given our limited resourcing, to the themes/modes for Wikimedia products.

Should Codex start making a greater reliance on CSS custom properties to enable changes between different themes/modes on the client side?

I guess I'm not convinced that we need to support changing modes on the client side, but if this is a requirement, CSS custom properties are likely the way to go. I think the method used in this patch is a good stop-gap measure to enable us to continue using Less while outputting some tokens as CSS custom properties. That said, it does obscure what's happening a bit, which could lead to confusion for Codex developers, so it's probably better to aim to write Codex styles in CSS in the future. We also should consider exporting all color tokens as CSS custom properties to avoid confusion over which tokens are output as what on the consumer's end.

Do we need to reorganize any of our current token system to support these goals?

I think the reorganization you've proposed in your proof of concept makes sense. I'd recommend not calling the decision layer theme.json though..."theme" is a confusing word and you could argue that it's better applied to the options layer as it currently is. Instead, I'd let the decision file remain codex-base.json, and in the future we can add codex-night.json etc. (although I also like the single-file approach proposed by Danny Banks). I do like the rename of theme-wikimedia-ui.json to options.json.

Change 994343 had a related patch set uploaded (by Catrope; author: Eric Gardner):

[design/codex@main] [PoC, DNM] tokens: organize into options/theme/component tiers

https://gerrit.wikimedia.org/r/994343

I think the reorganization you've proposed in your proof of concept makes sense. I'd recommend not calling the decision layer theme.json though..."theme" is a confusing word and you could argue that it's better applied to the options layer as it currently is. Instead, I'd let the decision file remain codex-base.json, and in the future we can add codex-night.json etc. (although I also like the single-file approach proposed by Danny Banks). I do like the rename of theme-wikimedia-ui.json to options.json.

+1, the output files are also named theme-wikimedia-ui.less, theme-wikimedia-ui-legacy.less, etc., and in fact there is an output file named theme-wikimedia-ui.json whose contents are different from the input file named theme-wikimedia-ui.json! That's confusing, so maybe we can reserve the theme- prefix for output files.

Change 1003500 had a related patch set uploaded (by Eric Gardner; author: Eric Gardner):

[design/codex@main] ADR 8: Token organization

https://gerrit.wikimedia.org/r/1003500

I'm pretty convinced that we should not worry about this. Codex is the design system for Wikimedia, so I think it's okay to limit ourselves, especially given our limited resourcing, to the themes/modes for Wikimedia products.

Do you consider web community projects using Codex to be "outside of WMF projects"?

Also, what are "re-skinned versions of the design system"? Like someone redefining each rules with news values and thus their theme will derive from your officials themes/palettes/colors (I don't know)?

I agree that dark mode color values should exist within Codex. I think the current color palette should be expanded from a base, or options, perspective. Then the different modes would just use different option tokens within the application tier.

Overall, from a design perspective, I support this proposal for handling tokens.

I'm pretty convinced that we should not worry about this. Codex is the design system for Wikimedia, so I think it's okay to limit ourselves, especially given our limited resourcing, to the themes/modes for Wikimedia products.

Do you consider web community projects using Codex to be "outside of WMF projects"?

Maybe the better way to say this would be: support for non-WMF projects that might want alternative branding colors, etc. is out of scope at this time. Right now the goal is to provide a "night mode" palette for our existing design system, and the proposed architecture seeks to do that in the most efficient and maintainable way possible.

Also, what are "re-skinned versions of the design system"? Like someone redefining each rules with news values and thus their theme will derive from your officials themes/palettes/colors (I don't know)?

Sort of – right now we're talking about using Style Dictionary (the tool we use to manage design tokens in Codex) to publish alternative "color modes" that override certain color tokens but don't otherwise radically change the look and feel of the site. A more radical customization (different branding colors, different fonts, etc) is also possible (this is one example of how you might do it in Style Dictionary), but as I mentioned above I believe this is out of scope for our current work here.

I agree that "theme" should not be the terminology used for what we're trying to achieve here. I think "color scheme" is actually most accurate and aligns with modern CSS standards, but we can stick with "modes" if we want to keep it slightly more generalized (not referring explicitly to color).

In my opinion, "themeability" has more to do with providing a completely different set of options tokens, or what has been referred to in the comments above as "re-skinning" or "branding". I'm in agreement that since Codex is designed to be the design system for Wikimedia, supporting these use cases is not a priority. This is why T296689 is in the Parking Lot column of the roadmap.

I think the reorganization you've proposed in your proof of concept makes sense. I'd recommend not calling the decision layer theme.json though..."theme" is a confusing word and you could argue that it's better applied to the options layer as it currently is. Instead, I'd let the decision file remain codex-base.json, and in the future we can add codex-night.json etc. (although I also like the single-file approach proposed by Danny Banks). I do like the rename of theme-wikimedia-ui.json to options.json.

+1, the output files are also named theme-wikimedia-ui.less, theme-wikimedia-ui-legacy.less, etc., and in fact there is an output file named theme-wikimedia-ui.json whose contents are different from the input file named theme-wikimedia-ui.json! That's confusing, so maybe we can reserve the theme- prefix for output files.

I'm thankful for these inputs.
I will share here some thoughts that I've also tried to put also more contextually on the ADR patch in regards to the connected and a bit more confusing to me (and possibly bit outdated) options/theme/components patch:

The current tokens architecture has been defined as a three tier architecture: theme-*/base/components. Under the following premises:

  1. Themeability within certain limitations for emphasizing usabilty over themeability.
  2. Centralization
  3. Abstraction of the option names for theme flexibility.

Another driving idea was to have just one file, the theme- JSON for themers to change centrally. We could also go the skin variables path and define one theme as leading and the others just providing overrides.

Clarifying once more, thanks @CCiufo-WMF for the message above.
A theme is a whole UI informing set of options. It includes all theme options to build the interface in different modes (dark/light, print, dyslexic readability)
The palette lives as option but it's an already made-up choices of 35 color values out of for example a color spectrum like RGB with 16.7 million colors.
A different theme would always have to deal with this pre-made limitation, but it would make it's most important choices in its value definition!
That's where the theme's look and feel is decided. All the other decisions later on are limited to mostly just changing the values.

I've brought the example of Firefox themes in the past here several times. While in the beginning these themes were free to do everything in the evolution (seeing the maintenance overhead) they were only allowed to change a few colors and background-images anymore.
If we put all the effort into researching usability and user-experience best practices, we don't have to loosen towards free choices more than in a reasonable manner.
You could for good reasons just choose within a slim band of possibilities the look and feel.
That's why the theme option values live in the first layer.

Maybe we're actually very close from each other in the ADR proposal @egardner, you've already amended your approach in details.
The theme-options, and the application and component layer isn't that different. Application is actually making more sense to me than -base, at least on a file name base (ha!).

The dark/light output would in my opinion also be possible by
theme-wikimedia-ui.json and a theme-wikimedia-ui-mode-dark.json.

Interestingly here, we aim to have the same final token names (e.g. color-base) with different values for those two modes. Same goes for dyslexic font-family-base. As those should specifically be used in all core, extensions and skins using those tokens.
For something like print we want to define an extra group of tokens that will overtake all elements, at least in the current approach in Vector.

Change 1003500 merged by jenkins-bot:

[design/codex@main] ADR 8: Color modes and token organization

https://gerrit.wikimedia.org/r/1003500

Change 1008950 had a related patch set uploaded (by LWatson; author: LWatson):

[mediawiki/core@master] Update Codex from v1.3.3 to v1.3.4

https://gerrit.wikimedia.org/r/1008950

Test wiki created on Patch demo by ATomasevich (WMF) using patch(es) linked to this task:
https://patchdemo.wmflabs.org/wikis/cd11cbf23a/w

Change 1008950 merged by jenkins-bot:

[mediawiki/core@master] Update Codex from v1.3.3 to v1.3.4

https://gerrit.wikimedia.org/r/1008950

Change 994343 abandoned by Eric Gardner:

[design/codex@main] [PoC, DNM] tokens: organize into options/theme/component tiers

Reason:

https://gerrit.wikimedia.org/r/994343