Design Tokens Resolver Module

Draft Community Group Report

Latest published version:
https://www.w3.org/design-tokens-resolvers/
Latest editor's draft:
https://design-tokens.github.io/community-group/
Editors:
Joren Broekema
Louis Chenais
Esther Cheran
Mike Kamminga
Andrew L’Homme
James Nash
Drew Powers
Matthew Ström
Lilith Whitman
Feedback:
GitHub design-tokens/community-group (pull requests, new issue, open issues)

Abstract

This specification extends the format and describes a method to work with design tokens in multiple contexts (such as “light mode” and “dark mode” color themes).

Status of This Document

This specification was published by the Design Tokens Community Group. It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Contributor License Agreement (CLA) there is a limited opt-out and other conditions apply. Learn more about W3C Community and Business Groups.

This is a snapshot of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C or the Design Tokens W3C Community Group Membership. Don’t cite this document other than as work in progress.

This document has been published to facilitate Wide Review.

This document was produced by the Design Tokens W3C Community Group, and contributions to this draft are governed by Community Contributor License Agreement (CLA), as specified by the W3C Community Group Process.

GitHub Issues are preferred for discussion of this specification.

1. Introduction

This section is non-normative.

Design tokens often need to express alternate values in different contexts. What defines a “context” is up to the user to determine, and is unique to their usecases. But common examples of contexts are:

A resolver outlines a way to generate different end values (or sometimes even different tokens) to satisfy the needs for all these contexts. The general process is:

  1. Start from a base set of tokens
  2. Apply modifiers based on which context(s) we are in
  3. The end result is a complete token set with context-appropriate values.

One would simply repeat the process once per the number of end-contexts being generated.

2. Terminology

2.1 Resolver

The mechanism by which multiple possible values of design tokens are reduced to a single value, i.e. this module.

2.2 Context

Context is up to the end user to define, but is “any condition that requires a different value for a design token.” There are no official contexts in this specification.

2.3 Set

Subsets of tokens that collectively form the default base set. Users SHOULD ensure the sum total of sets contain mutually exclusive tokens, i.e. they don’t overwrite one another and may be combined in any order to produce the same result.

2.4 Modifier

Mapping of contexts to token impacts. Modifiers MAY accept an input that determine the final token values after the resolver has run.

2.5 Input

The user’s selection for the modifiers, expressed as a key–value map. See example.

2.6 Resolution

The process of combining token sets and applying modifiers based on the specified inputs to produce the final set of tokens.

Issue 1
Issue 2

2.7 Orthogonal (orthogonality)

The characteristic of modifiers that do not overlap with one another, i.e. operate on different tokens. Modifiers MAY be orthogonal, but it are not required to be.

3. Syntax

3.1 Resolver file

A resolver is a JSON object with the following properties:

Name Type Required Description
name string A short, human-readable name for the resolver.
version YYYY-MM-DD Y Version, expressed as a ISO 8601 date.
description string Additional information about the resolver’s purpose.
tokens (Set | Modifier)[] Y Resolution order of tokens.

Users SHOULD name resolver files with a .resolver.json syntax.

3.2 Name

A resolver MAY provide a human-readable name. This is used to identify the resolver.

3.3 Version

MUST be 2025-10-01. Reserved for future versions in case breaking changes are introduced.

{
  "name": "Marketing Design System",
  "version": "2025-10-01"
}

3.4 Description

A resolver MAY provide additional information.

3.5 Tokens

The tokens key is an array that may contain any combination of sets and modifiers. The order is significant, with tokens later in the array overriding any tokens that came before them, in case of conflict.

3.5.1 Set

Name Type Required Description
type "set" Y MUST be "set".
name string Optional human-readable name for this set.
sources <token-defs> Y The tokens that belong to this set.
3.5.1.1 Shortened syntax

File strings from sources MAY be hoisted into the top-level tokens array as a simpler syntax.

Inline tokens (objects) MUST NOT ever be declared in tokens. An object inside tokens MUST be either a set or modifier.

3.5.2 Modifier

A modifier can be thought of as a “conditional set,” where its contents depends on an external input. T

Name Type Required Description
type "modifier" Y This MUST be "modifier".
name string Y The name of the modifier. This MUST be unique among other modifiers in the same file.
context Record<string, &lt;token-set>> Y A key–value map of contexts to <token-defs>.
default string Optional default value. MAY be provided in case the input doesn’t require this value.

Tools MUST throw an error if 2 modifiers with the same name are declared in tokens.

3.6 Inputs

An input is a mapping of modifier names to modifier values declared in any resolver. Inputs are not part of the resolver file itself, rather, provided to the tool alongside the resolver. A resolver that declares any modifiers MUST be consumed with an input as options.

An input SHOULD be serializable to a JSON object. Meaning, an input MAY be expressed in any programming language, but that expression should be easily converted back into a JSON object. Related concepts would include an object in JavaScript or a dictionary in Python.

Tools that load a resolver that declares modifiers SHOULD throw an error if an accompanying input is not provided.

3.6.1 Orthogonality

Modifiers are said to be orthogonal when they do not operate on the same set of tokens. In practical terms, if modifiers are orthogonal, then the order in which they are applied isn’t significant since they will produce the same values.

Implementors SHOULD make modifiers orthogonal. Tools MAY decide how to handle non-orthogonal modifiers.

3.7 <token-defs>

An array consisting of:

Any other inputs are invalid.

The array order is significant, where tokens with the same name overwrite previous instances of that token, if any.

3.8 $extensions

An $extensions object MAY be added to any set, modifier, or object in this spec to declare arbitrary metadata ignored by tooling. Its purpose in a resolver is the same as in the format.

4. Resolution Logic

Tools MUST handle the resolution stages in this order to produce the correct output.

  1. Input validation
  2. Token flattening
  3. Resolution

4.1 Input validation

Tools MUST require all inputs meet the schema described in that resolver’s modifiers syntax.

If a resolver does NOT declare any modifiers, skip this step and proceed to Sets flattening

  1. For every key in the input object:
    1. Verify it corresponds with a valid modifier. If it does not, throw an error.
    2. Verify that key’s value corresponds with that modifier’s allowed values. If it does not, throw an error.
  2. For every modifier in the resolver:
    1. If that resolver does NOT declare a default value, verify a key is provided in the input. If not, throw an error.

4.2 Token flattening

Tools MUST iterate over the tokens array in order.

4.2.1 Sets

  1. Sets are loaded in the tokens array order.
  2. If this uses simple syntax (string), treat it as if it is a set with no name, with a single item in the sources array.
  3. Every token reference in sources MUST be resolved in array order.
  4. For every token reference, merge with the previous set.
  5. Aliases MUST NOT be resolved yet. That must happen at the end. Aliases MAY refer to values that will be supplied in upcoming steps.

4.2.2 Modifiers

Every modifier is applied in order, taking in the external input inputs.

  1. For that modifier, load the corresponding input value.
    1. If there is not an input value, load the default context.
    2. If there is neither an input value nor default context, throw an error and stop resolution.
  2. Load the context’s appropriate <token-defs> array that corresponds to the input value.
  3. Flatten the <token-defs> array into the existing basis, in array order.
Issue 3

4.2.3 Conflict resolution (flattening)

Conflict resolution occurs when flattening sets or applying modifiers, and a token name appears by tokens of different values, from different sources. In many cases, this is intentional, but not always.

When 2 tokens try and occupy the same space, tools MUST resolve the conflict in the following manner:

  1. If the token types are identical, overwrite the latter value with the former.
  2. If the token types are incompatible, the tool MUST throw an error.
  3. If one name is a token, and the other is a group, the tool MUST throw an error.
  4. If one value is an alias (i.e. the $type is unknown), overwrite the value.

4.3 Alias resolution

Alias resolution may only done after all sets and modifiers are handled, and there are no other tokens to merge in. Resolve aliases the same way as outlined in the format, allowing deep aliases but erring and stopping resolution on circular aliases and/or aliases that point to unresolvable types (such as aliasing a dimension token inside a gradient token, which is invalid).

4.4 Resolution

After all aliases resolve correctly in the final set, the end result is one tokens object, that behaves as if it was a single JSON file to begin with.

5. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words MAY, MUST, MUST NOT, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

Tools implementing the Resolver Specification MUST:

A. Acknowledgments

This section is non-normative.

This resolver spec wouldn’t have happened without the Hyma Team, including but not limited to Mike Kamminga, Andrew L'Homme, and Lilith. Significant contributions were also made by Joren Broekema, Louis Chenais. We thank the members of the Design Tokens Community Group for their contributions and feedback.

B. References

B.1 Normative references

[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174