Skip to content

dzearing/token-resolution

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

How do we resolve tokens?

Tokens are a design-specific construct that enable implementers to override specific aspects of a component's look and feel. It is expected that tokens will be layered on top of one another.

For example, a base design will establish the set of tokens and their default values. A team building an application might set a token to a specific value for the entire application. Further, a component of the application might further customize the component and override yet another aspect of the look and feel. In this example, there are 3 discrete layers of tokens. It is desireable that all 3 layers have the ability to affect one another.

This repository is an exploration of how layers might affect one another, and how various APIs feel to use.

What do tokens look like?

At the most basic level, tokens are an object literal, or a function that return values from a provided theme. Some obvious implementations of tokens are...

// return a const set of tokens
const tokens = () => {
  return {
    baseColor: "#fff"
  };
};

// return a set of tokens based on a theme
const tokens = (theme: Theme) => {
  return {
    baseColor: theme.colors.base
  };
};

// return individual tokens based on a theme
const tokens = {
  baseColor: (theme: Theme) => theme.colors.base
};

As components are developed, individual layers become separated in time and space. For example, baseColor might be defined in a basic design layer, then overridden in an application-specific implementation of the component.

The semantics of how layers interact and how tokens become dependent on one another is non-trivial, so multiple prototypes exist to examine approaches.

Approaches

There are 2 approaches in this repo, resolving-tokens and middleware. Qualitative "pros and cons" are put forth below.

Implementation complexity

Category Aspect resolving-tokens middleware
Ergonomics Feel ❌ (ref) ❌ (ref)
Functionality Interdependent tokens
Functionality Object literals
Functionality Theme based values
Functionality Token modification ❌ (ref)
Implementation Complexity

resolving-tokens-feel

The interface for a token is a bit fuzzy when it comes to the "dependency description". It does feel similar in spirit to using react hooks, but prevents the use a type checker.

const t = { value: "abc" }; // constant

const t = { value: (t: any) => t.colors.brand.value[0] }; // lambda

const t = {
  // dependency description
  value2: {
    dependsOn: ["value"],
    resolve: (theme: any, [value]: any) => value.value + "def"
  }
};

middleware-feel

Middleware pulls ideas from web server middleware, where each layer has the ability to influence the behavior before and after layers "below" it in the stack.

It allows for more flexibility, but at the cost of higher complexity.

const t = { value: "abc" }; // constant;

const t = (theme: any) => {
  // function
  return {
    value: theme.colors.brand
  };
};

const t = (theme: any, baseTokens: ResolvedTokens, next: TokenCallback) => {
  // next is the token generator for the layer being composed.
  // with this, the "top" component gets the ability to modify tokens that
  // are used in computation in lower layers, as well as the ability to override
  // any results.
  const tokens = next(baseTokens);
  return {
    ...tokens,
    value2: tokens.value + "def"
  };
};

resolving-tokens-modification

It is a reasonable scenario that for a given component, an implementer would want to define a token's value as "some contstant larger than it was in a lower layer". For instance (in pseudocode): fontSize: previousFontSize + 2px;

In the resolving-tokens model, all layers are flattened into a single dictionary, then tokens are evaluated. This prevents a component from seeing what value a token had before it was redefined.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages

  • TypeScript 99.1%
  • JavaScript 0.9%