Page MenuHomePhabricator

Evaluate variables aka tokens abstraction
Closed, ResolvedPublic

Description

One of the current differences in WVUI and Wikit is the variables (design tokens) abstraction.

Comparison of design token abstraction approaches

Wikimedia Vue UI has been relying on WikimediaUI Base, which has seen an initial implementation based on OOUI widgets.
It has been following the idea of

  • base variables that are applied in as many components as possible to clearly indicate going away from those -base variables needs to have a strong cause to add an extra variable

Many of above goals have been captured in WikimediaUI Base.

Wikit applies three type of variable levels:

  • global (taking WikimediaUI base variables as values)
  • alias
  • component-level tokens

Additionally Wikit relies on JSON format for support of native platforms.

Please check WiKit's documentation to find out more about the use of design tokens in the context of the Wikidata/Wikibase design system.
Also have a look at the tokens listing https://wmde.github.io/wikit/?path=/story/design-tokens-colors--page

Open questions

  • Abstraction issues to hunt down source of an issue (which in turn might lead to a lot of unnecessary overrides and less consistency)
    • Reduce abstraction to only necessary level by reducing to component override tokens
  • …together with additional level of abstraction in component-level tokensLayers of abstraction: 1. Direct CSS value, 2. Foundational style (example color value), 3. Base variable/token, 4. Abstracted group token (@border-color-input-binary--active), 5. Sinlge component token (@border-color-radio--active)
    • Reflected in the elected proposal
  • WiKit: Why is redefinition of base into global necessary?
    • It's not.
  • How do design tokens “ensure component reusability”?
    • Limiting tokens to a shared, overseeable vocabulary, that ensures consistency, reducing the danger of too many one-off component overrides.

Conclusion from the Vue.js taskforce convening:

Follow WMF approach w. rare exceptions of single-use components tokens in separate file

Settle on base tokens file for general and grouped (f.e. input-binary specifics) tokens and on component tokens file, which will contain single-component-tokens only when needed.

Related Objects

Event Timeline

Volker_E renamed this task from Evaluate (and implement) variables abstraction to Evaluate (and implement) variables aka tokens abstraction.Feb 1 2021, 5:50 PM

The WMDE team involved in the conception of our design system already provided an overview of the benefits attached to the use of JSON tokens in the context of WiKit a while ago in this presentation. Now this document tries to also collect the drawbacks of our current solution.

JSON tokens were originally adopted by our team because they represented the most theoretically ideal solution in the market (e.g. Salesforce, Adobe). We wanted to try whether this stictly agnostic and scalable approach would work in our scenario.

So far, we’ve been able to use JSON tokens organized in three levels of abstraction to embed design decisions in our components, since they didn’t present any critical limitations in our workflow. But the set-up, of course, doesn’t come without some downsides (majorly related to the use of component-level tokens, as described by the document). We agree that there’s room for improvement, and we'd be keen to collaborate to get there through exploration, in order to come up with the most convenient solution in the specific context of WVUI.

Thank you @Sarai-WMDE for the insights and the detailed write-up of WMDE's token approach.

At the Foundation and its web products we went similar ways a while ago, mostly being able to exchange variable (WikimediaUI Base) with tokens 1:1 when looking at the WMDE goals of having a

  • consistent,
  • single source of truth for design,
  • in a set of predefined, centralized and traceable design decisions

Additionally we also provide the advantage

Current shortcomings in contrast to WMDE yet:

  • “It’s in the tokens or it does not exist”

We've been nearly completely putting all “rich” CSS values in OOUI's WikimediaUI theme into variables, with only exceptions 0, inherit, or resets to default values. But we haven't put more than base/alias variables and a small number of component variables into WikimediaUI Base yet.

  • Components definition outside of OOUI's code base not fully available via WikimediaUI Base
  • Handover in tokens between design and development not a must-have yet.

From an resource-budgeting/maintenance overhead concerned perspective, but also from an implementors point of view I see a big issue with the component-level tokens:

  • There is a lot of repetition and aliasing between the global/alias token level (example provided in Wikit ADR) and component tokens.

image.png (394×2 px, 78 KB)

The repetition (not DRY) is time-consuming and maintenance intensive. For every new component a large set of component specific variables has to be defined. Additionally it doesn't save from one of the biggest risks with tokens, the abstraction. Imagine a global token would be changed, with component tokens you'd have a third inherited level of abstraction, that is out of clear view when impacted by such higher-level change.

Therefore I'd strongly recommend to go a CSS way of implementation.
From general to specific: Use aliased base variables when applicable and only define component-level tokens when specifically needed. Thinking of a handover where the component design would still include all tokens needed, but switch between base/alias and component specific ones. This way would also ensure not to invent too many new ones and provide an extra sanity check on design/implementors side as every new component token definition should let people stop and consider the decision for a moment. And possibly lead to more consistency across the interface altogether.

Other action points are tackling shortcomings from above for Foundation side.

The technological agnosticism of JSON might be of small interest for usages in apps, but we'll also have to assume that Cascading Style Sheets or derived pre- and post-processors are remaining a relatively simple central technology for providing style definitions. And even when apps are asking we could implement with a JSON translation of the currently available variables in CSS and LESS with clear scoped need in future.

Also, for simplicity, we should probably settle on “design tokens” for these – no matter which technology is underlying.

Traceability* is another process question, as it comes down to documentation and process. Just because it's a token doesn't make automatically clear why this value was chosen. Was it due to prior work, context, requirements like accessibility or internationalization etc.?

  • See goal “traceable design decisions”

One detail, that might have arisen just from the unclarity and the need to separate concerns in Wikidata Design System approach is the differentiation between base and global levels. Base should be the global level in thinking of the WikimediaUI Base variables approach.

There's no unclarity or need to separate concerns at the base of that "distinction", which truly doesn't exist either in WiKit: it was just a terminology choice. Base and global levels are also conceptually the same in our approach.

AnneT renamed this task from Evaluate (and implement) variables aka tokens abstraction to Evaluate variables aka tokens abstraction.Jul 19 2021, 9:24 PM

Considering the above recommendation:

Therefore I'd strongly recommend to go a CSS way of implementation. From general to specific: Use aliased base variables when applicable and only define component-level tokens when specifically needed.

  • What would be the granularity of "component-level" implied by this approach? Are these single-use variables or are they shared by a component category (e.g. input, button)? If the former: Would they be documented in Wikimedia-ui-base too? In which cases would they be preferred to global/base variables?

And following up on what's probably implied by:

Other action points are tackling shortcomings from above for Foundation side.

We could have an exchange on our individual teams' experiences with component specification. It would be interesting to hear from WMF:

  • How easy and convenient is it (or does it sound) to use Wikimedia UI base variables as values for specification? What's the "coverage", in terms of styles, that the file offers (can they always find the values they are looking for)? And how do they expect for variables to be modified, added or removed? Is the source code a suitable source of spec values, or would they appreciate some sort of preview?

Quick comment that's probably obvious, but from a developer standpoint, one thing I would prioritize is ease of use/visibility during development. Two concerns:

  • In MediaWiki extensions, we use a pretty manual process to include and update Wikimedia UI base, which must be set up per-extension
  • In WVUI (and any codebase that properly uses Wikimedia UI base as an npm module), it's easy to include and update the library, but difficult to view it. I have to open up the variable sheet elsewhere, or dig into node_modules

Edit: I think what would be most ideal is visualization of tokens in Storybook like it's done in WiKit.

A counter-point to my conviction, from Adobe Spectrum:

Use component-specific tokens for their respective component
When building Spectrum verified components, use component-specific tokens. This ensures that as a component’s design evolves, you won’t have to retrace any higher-level design decisions that informed the updates. It’s not recommended to use component-specific tokens interchangeably with other components, unless one is derivative of the other.

Some thoughts post-Designer summit:

Designer-developer handoff

This could use stronger definition. Is the designer creating tokens for some values in Figma? Will the designer and developer meet to discuss which tokens will likely be needed? Or will this happen during the development process? I ask because during our experimental WVUI development, we would identify component-specific tokens that were needed while building the component, since these values sometimes depend on the template and stylesheet structure (e.g. will it be a margin-left or a margin-right?) It's hard to imagine being able to accurately identify and name all tokens solely based on the design.

Where do component-specific tokens live?

Initially I thought they should live along with the component code in the shared library, but @Tonina_Zhelyazkova_WMDE brought up an excellent point that tokens should be technology-agnostic (e.g. what if someone needs the token and is building in OOUI rather than Vue?) So, they should probably live along with the base tokens in Wikimedia UI Base. However, if we have to add or update a token during development in the shared component library, we would have to update a separate repository, create a new release, then consume that new release. We have been following this process in WVUI development so far and it is quite inefficient. I would propose we consider a monorepo setup that includes the shared component library and WikimediaUI Base as separate but related exports to resolve this inefficiency.

Token visualization

From the development side, easy access to tokens during development is important. Right now, I have to open the Wikimedia UI Base file somewhere separate from where I'm working, which is inconvenient. I would propose doing something similar to what WMDE has done in WiKit to visualize design tokens within Storybook (which would be possible if we did the monorepo setup mentioned above).

Another practical question: when does a value become a design token? This is the process I've been following:

  1. Is it a simple keyword, like display: flex? If so, probably don't use a token, unless it's something that gets repeated a lot like the value of cursor: disabled
  2. Is it a simple value, like width: 100% or margin: 0? If so, probably don't use a token
  3. Is there an existing token in Wikimedia UI base whose name makes semantic sense for this component-specific use? e.g. border-color: @border-color-base? If so, just use the Wikimedia UI base token
  4. Is there an existing token in Wikimedia UI base but the name doesn't make semantic sense for this component-specific use, like background-color: @color-primary--active or border-color: @wmui-color-base20? If so, create a new component-specific token
  5. If none of these things are true, create a new component-specific token

There's a lot of gray area in here, though, especially step 2. I looked through some WVUI components I've built and found some examples of values for which I did not create a token:

  • outline: 1px solid transparent
  • content: ' '
  • top: 50%
  • border: @border-width-base @border-style-base transparent
  • transition: background-color @transition-base, border-color @transition-base, border-width @transition-base;

Those could all be debatable. The goal would be to take the debate out of it as much as possible with clear instructions on when one should create a token.

Volker_E updated the task description. (Show Details)

Thank you so much for collecting all those valid thoughts here, @AnneT
Adding my two cents to each one of your points, based on our experience with WiKit, and trying to keep in mind the new context:

Designer-developer hand off

Although I'd say this is still up for validation with the UX teams, designers should ideally be able to use tokens as values for specification. This means that they should select (e.g., from a visualization in Storybook) and document (in Figma) the tokens that apply to each individual property of the component that they are designing, in preparation for handover. Designers and developers should meet to validate and, if needed, complete said specifications together. For this to be possible, an exhaustive set of predefined design decisions should be made available early on. That first batch of tokens should document all known stylistic values (e.g. available border colors, background colors, heights, border-radius, etc.), and it might be subject to change (additions, modification, deletions) as the system evolves.

Where do component-specific tokens live? + Token visualization

I'm glad you're considering a monorepo setup. I know this would be encouraged by the developers involved in the creation of our design system. As you mention, this would reduce inefficiencies and provide better access to the design tokens (whichever their format) during implementation, also allow their visualization in Storybook, which is convenient.

Also adding some inline responses to your last comment:

Another practical question: when does a value become a design token?

This should primarily be a design decision. Tokens are used to document and propagate predefined system styles. Detecting which those styles are, naming and organizing/grouping them, should be the responsibility of the system designer(s).

This is the process I've been following:

  1. Is it a simple keyword, like display: flex? If so, probably don't use a token, unless it's something that gets repeated a lot like the value of cursor: disabled
  1. This matches our approach. We originally "over documented" styles, and ended up having to remove tokens that did not represent a design decision, but only translated a choice among default CSS values. Curiously enough, we actually got rid of cursor tokens!
  1. Is it a simple value, like width: 100% or margin: 0? If so, probably don't use a token
  1. Agreed, although we did document width: 100% as "full-width", a token that applies to all our block-elements by default. We also work with 50% and 200% (width-double), but I can see why this might not be necessary. Maybe it might be worth agreeing on the definition of "simple value". One of its characteristics might be the fact that it doesn't belong to a scale.
  1. Is there an existing token in Wikimedia UI base whose name makes semantic sense for this component-specific use? e.g. border-color: @border-color-base? If so, just use the Wikimedia UI base token
  2. Is there an existing token in Wikimedia UI base but the name doesn't make semantic sense for this component-specific use, like background-color: @color-primary--active or border-color: @wmui-color-base20? If so, create a new component-specific token
  3. If none of these things are true, create a new component-specific token

This all sounds about right, but I would encourage the DST to prevent the creation of said single "component tokens" as much as possible. Meaning: Wikimedia UI base (or whichever token solution is built from it, T288383) should ideally anticipate and provide an exhaustive and organized list of the available, premade design decisions that communicate intent and can be used with as many components as possible, all in order to centralize and propagate the system's source of truth.

For example, looking at margin-right: @margin-end-typeahead-suggestion-thumb; , I assume that this component level token had to be created because there's no record of all the predefined system spacing values. In the context of WiKit, we'd select one of the reusable tokens from the spacing scale (e.g. $dimension-spacing-medium) to define the value of our component-level token (which we'd later use as the final styling value).

There's a lot of gray area in here, though, especially step 2. I looked through some WVUI components I've built and found some examples of values for which I did not create a token:

  • outline: 1px solid transparent
  • content: ' '
  • top: 50%
  • border: @border-width-base @border-style-base transparent
  • transition: background-color @transition-base, border-color @transition-base, border-width @transition-base;

Those could all be debatable. The goal would be to take the debate out of it as much as possible with clear instructions on when one should create a token.

I'd say that, except for content:' ', all the listed properties could be defined using tokens or composite tokens, in case the creation of an alias is not justified.

Thank you, @Sarai-WMDE, for your thorough response! It's really helpful to learn from your experience with design tokens in WiKit so far.

I have some remaining questions/thoughts about one topic, but everything else seems clear to me.

This all sounds about right, but I would encourage the DST to prevent the creation of said single "component tokens" as much as possible. Meaning: Wikimedia UI base (or whichever token solution is built from it, T288383) should ideally anticipate and provide an exhaustive and organized list of the available, premade design decisions that communicate intent and can be used with as many components as possible, all in order to centralize and propagate the system's source of truth.

This makes sense, although it's something I didn't fully understand about the design token architecture proposal until now. Single-component-specific variables are used widely in OOUI and WVUI in the name of theming (something that actually exists in OOUI, and could potentially exist in WVUI). I was thinking the design token architecture would apply to these variables, too, but perhaps it would be more accurate to say that we will try to expand WikimediaUI base with more tokens that come from design decisions and can be used by components, but that we will keep single-component variables separate.

All in all, I think I will be able to best understand this whole process once we start experimenting with it! I hope we can do this within the shared library as soon as possible.

Sorry about the late response! Here are my thoughts:

[...] but perhaps it would be more accurate to say that we will try to expand WikimediaUI base with more tokens that come from design decisions and can be used by components, but that we will keep single-component variables separate.

That would be ideal. I have to say that I'm not familiar with how single-use/component-specific variables are used in OOUI. I'm only aware of how they're intended to "document" exceptions (aka used instead of missing aliases) in WVUI components. What's for sure is that, if there's anything that tokens can help with, that's theming.

Let my clarify the following sentence, just in case:

I would encourage the DST to prevent the creation of said single "component tokens" as much as possible.

Being more direct, this simply means that the detection of a missing alias should encourage the DST to reconsider whether a new alias token needs to be created, instead of directly triggering the introduction of an exception.

Also, for extra clarification (I'm sure you already know this, Anne): In the context of WiKit (an many other design systems), component tokens are part of the token solution. They're the highest level of abstraction, and capture design decisions in their final context (+ have some other technical benefits, like allowing the introduction of style updates without resulting in breaking changes). I know they received push-back, but they are such common practice that I hope we'll still be able to consider their benefits.

All in all, I think I will be able to best understand this whole process once we start experimenting with it! I hope we can do this within the shared library as soon as possible.

Definitely! Can't wait to understand all the requirements better and provide all possible support to materialize a solution.

There's a lot of gray area in here, though, especially step 2. I looked through some WVUI components I've built and found some examples of values for which I did not create a token:

  • outline: 1px solid transparent
  • content: ' '
  • top: 50%
  • border: @border-width-base @border-style-base transparent
  • transition: background-color @transition-base, border-color @transition-base, border-width @transition-base;

Those could all be debatable. The goal would be to take the debate out of it as much as possible with clear instructions on when one should create a token.

I'd say that, except for content:' ', all the listed properties could be defined using tokens or composite tokens, in case the creation of an alias is not justified.

For the colors it's absolutely necessary to provide them as tokens, as themeability might be negatively impacted. For functionality like certain accessibility features, we might remain with a more static token implementation. Theming should and will be limited to a certain extent to not negatively impact users of the library.

Volker_E claimed this task.

Conclusion from the Vue.js taskforce convening:
Proposal on “2 levels vs 3 levels of abstraction (do we need the final level, component tokens)?” with vote results: WMDE approach 2 - WMF approach w. rare exceptions of single-use components 7 - abstain 3

We're settling on base tokens file for general and grouped (f.e. input-binary specifics) tokens and on component tokens file, which will contain single-component-tokens only when needed.

Another practical question: when does a value become a design token? This is the process I've been following:

  1. Is it a simple keyword, like display: flex? If so, probably don't use a token, unless it's something that gets repeated a lot like the value of cursor: disabled

Follow-up on cursor tokens in T302181#7724398 (tl;dr for themability reasons it seems useful to tokenize them)