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:
- 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.
- 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).
- 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.