Page MenuHomePhabricator

[SPIKE] Investigate Codex support for CSS custom properties
Closed, ResolvedPublic8 Estimated Story PointsSpike

Description

The Web team is working on T352198: [Spike, carryover] Should MediaWiki codebases use CSS custom properties?, investigating the feasibility and desirability of using CSS custom properties for some or all design tokens in the MediaWiki ecosystem, which could more easily enable a dark mode feature.

Related to that, we should investigate:

  • How should Codex support this type of use of CSS custom properties? How could we made Codex components' appearance respond to a change in the value of one of these custom properties? Should this replace the current Less-variable-based system?
  • How can CSS custom properties containing Codex design token values best be made available in MediaWiki? Should this replace the Less variables we currently make available?
  • How does this impact downstream consumers of design tokens, like OOUI? See T353663 for the Web team's initial findings on custom properties and OOUI.

Acceptance Criteria:

  • DST engineers investigate the above questions and come to a shared perspective.
  • The investigation findings are documented and shared publicly for review and feedback.
Spike Findings (1/31/24)
Experimental Token Output and Codex build

Link to prototype patch

Codex uses a tool called Style Dictionary to manage and manipulate our system's design tokens. Style Dictionary supports the ability to output one set of tokens in a variety of formats – either predefined (LESS, JSON) or custom. After some trial and error, I was able to define a format that produced an "experimental" LESS file. Just like our normal output, this file contains all of our publicly-exported tokens as LESS variables suitable for use inside MediaWiki, with one important addition – the file begins with a plain CSS :root declaration which defines CSS custom properties for an arbitrary subset of our design tokens (since this is intended to support a future dark mode, I chose to handle most color-related variables in this way). These variables are also defined in LESS (which is how Codex components normally access them for their component-specific styles), but the values here simply refer to the CSS custom properties.

Below is an abridged example of how this new output compares to what we produce currently:

theme-wikimedia.ui.less (old version)
/* Normally, all tokens are resolved to static values for LESS variables */

@color-primary: #36c;
@font-family-base: sans-serif;
theme-wikimedia.ui-experimental.less (experimental version)
/* Any exposed tokens would be defined here as CSS custom properties */
:root {
    --color-primary: #36c;
}

/* The LESS variable definition now refers to the CSS variable */
@color-primary: var( --color-primary );

/* including a fallback value is also possible. If we wanted we could produce this: */
/* @color-primary: var( --color-primary, #36c ) */

/* Non-exposed values remain unchanged */
@font-family-base: sans-serif;

Once we have this "experimental" set of tokens (where some token values refer to CSS custom properties), we can generate a corresponding "experimental" build of Codex where this new set of tokens is used for the final component styles (which are output as CSS files).

This will result in styles like this being shipped to the client:

.cdx-card {
  background-color: var(--background-color-base);
  display: flex;
  align-items: flex-start;
  position: relative;
  border: var(--border-base);
  border-radius: 2px;
  padding: 12px;
}

Styles which refer to "exposed" tokens will now look for CSS variables of the same name; other styles are unchanged. One important thing to note here is that the Codex styles would not include a :root declaration. Instead, the idea is that a pre-existing root declaration would live on the page containing the default values of all custom properties, and then other CSS selectors or media queries could override those values where needed. Codex could provide a CSS file containing the :root declaration for all the default values which Web could use somewhere, or we could build the styles so fallback values are included whenever --var() is called. If we did the latter, then Web would not need to define the initial state of these color values, only any dark-mode overrides.

Next steps: Short term

It is relatively simple to define a custom format in Style Dictionary and output a set of tokens (and styles) where some values are replaced with CSS custom properties. DST could ship a version of Codex that included these "experimental" tokens and stylesheets sometime in February.

However, this only gives Web the ability to override certain component styles easily. A dark mode color palette will still be necessary here. My assumption is that having a set of "theme-able" Codex components will be helpful to the Web Team as they work on developing a dark color palette and beta-testing it.

  • Next sprint – DST finalizes "experimental styles" prototype and releases a version of Codex that includes these new files
    • Question: Do we want to include fallbacks (var(--color-primary, #36c)) in these new files?
    • Question: Do we expose a particular subset of variables, or do we simply allow *all* tokens to be overridden in the experimental stylesheet? If we did the latter, we probably would want to include fallbacks, or else a really cumbersome :root declaration becomes necessary
    • Question: How do we ensure icons work properly (CSS-only icons in particular)? We may need to ensure our SVGs use properties like currentColor correctly in order to ensure that they are theme-able
    • If needed, DST can also help to set up some kind of theming sandbox to make it easier for Web to experiment with different color palettes
  • March 2024 – Web team begins beta-testing the new dark mode feature using the experimental codex styles
Next steps: Longer term

Exposing a set of Codex design tokens as CSS custom properties seems like a good short-term solution to help with Web's efforts to develop a dark mode color palette and beta test it with users. However, in the longer term, any dark mode palette should probably live within Codex itself so that other skins, extensions, and features can easily use it (and to ensure a consistent experience for users).

Once a good dark-mode color palette has been figured out, we should try to upstream this information into Codex and delete all of the experimental styles and token assets so that other projects don't start to rely on them.

Hopefully by this time Codex will have settled on a definitive "theming architecture" that will allow us to manage alternate sets of styles in an efficient and maintainable way. I have opened a proof-of-concept patch that explores one approach we could take, inspired by this article written by the creator of Style Dictionary.

This work should probably happen in parallel to the Web team's beta-testing of dark mode so that we have a more permanent solution ready in time for the final production launch of this feature.

  • Some point between March and June:
    • Dark mode color palette is finalized and these values are added as new tokens into Codex
    • Codex finalizes its theme architecture and can use these values to produce "official" dark-mode assets which can be used by Web in a way that meets production requirements

Details

Related Changes in Gerrit:

Event Timeline

CCiufo-WMF renamed this task from PLACHOLDER: Investigate Codex support for CSS custom properties to PLACEHOLDER: Investigate Codex support for CSS custom properties.Dec 11 2023, 5:09 PM
CCiufo-WMF set the point value for this task to 8.Dec 11 2023, 5:12 PM
CCiufo-WMF renamed this task from PLACEHOLDER: Investigate Codex support for CSS custom properties to Investigate Codex support for CSS custom properties.Jan 8 2024, 3:04 PM
CCiufo-WMF updated the task description. (Show Details)
CCiufo-WMF renamed this task from Investigate Codex support for CSS custom properties to [SPIKE] Investigate Codex support for CSS custom properties.Jan 8 2024, 6:10 PM
CCiufo-WMF changed the subtype of this task from "Task" to "Spike".
CCiufo-WMF changed the task status from Open to In Progress.Jan 23 2024, 7:45 PM

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

[design/codex@main] build, tokens: Experimenatal CSS output

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

This comment was removed by egardner.
egardner updated the task description. (Show Details)

Question: Do we want to include fallbacks (var(--color-primary, #36c)) in these new files?

Another tool we could potentially make use of is the postcss-custom-properties plugin for PostCSS. When the preserve option is set to true, it performs the following transformation:

/* Input: */
:root {
    --color-base: #202122;
}

.cdx-accordion {
    color: var( --color-base );
}

/* Output: */
:root {
    --color-base: #202122;
}

.cdx-accordion {
    color: #202122;
    color: var( --color-base );
}

In order to know which value each token has, it does require there to be a :root {} block in the input that defines each value, so we would either have to add that and then remove it again with postcss-remove-root, or inject it with postcss-global-data. Alternatively, it can operate on fallback values as well: it transforms color: var( --color-base, #202122 ); to color: #202122; color: var( --color-base, #202122 ); even in the absence of a :root {} block.

This could help us support older browsers that don't support CSS custom properties, if that's something we decide to care about.

Question: Do we want to include fallbacks (var(--color-primary, #36c)) in these new files?

This is cool. I think between what Style Dictionary gives us (for building the tokens) and what Vite & various plugins can do (for building the Codex styles themselves) we have a lot of flexibility in the output we can produce here.

This could help us support older browsers that don't support CSS custom properties, if that's something we decide to care about.

The only "browser" + versions in this category that have had page views in the past month are pre-Chromium Edge (0.002%), IE (0.095%), and Opera Mini (0.064%). Caniuse considers CSS custom properties to be "baseline".

Change 993056 abandoned by Eric Gardner:

[design/codex@main] build, tokens: Experimental CSS output

Reason:

Abandoned in favor of https://gerrit.wikimedia.org/r/c/design/codex/+/1003824

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