﻿---
title: Tokens and vars
description: Theme trees, lightDark, cq, contextualVar, and module-local vars groups.
url: https://docs-v3-preview.elastic.dev/distillate/concepts/tokens
---

# Tokens and vars
Author a nested value tree. `createDistillery` derives `CssToken` / `ScaleToken` leaves and the `themeVars` registry. Branded values stringify through `Symbol.toPrimitive`, which is why they interpolate into tagged templates.

## Theme tokens

```ts
const distillery = createDistillery({
  prefix: 'eui',
  themeScope: '.eui-view',
  theme: {
    colors: {
      ink: lightDark('#111', '#eee'),
      warning: '#FACB3D',
    },
  },
});
const { ink } = distillery.tokens.colors;
String(ink); 
ink.cssVar; 
ink.path; 
```

A string leaf is scheme-invariant (`light === dark`). `lightDark(light, dark)` is scheme-varying and both sides must be CSS `<color>` values. Emission uses `light-dark(light, dark)` when the two values differ. Unread theme tokens are pruned from the theme block.
`zipSchemes(light, dark)` folds two per-scheme trees into this form: equal strings stay bare, differing strings become `lightDark`, and `ScaleToken` leaves must agree.
Named variations go on `variations` in `createDistillery`. Declaring a variation does not emit it; name it at `renderStyles` with `{ flatten }` or `{ alternates }`. Variations extend the base only. `ScaleToken` leaves must match the base because they inline and cannot vary. See [declare and select variations](https://docs-v3-preview.elastic.dev/distillate/guides/theming).
`themeToken(path, cssVar)` remains the constructor derivation calls. Paths are slash-delimited (`colors/ink`), matching `themeVars` keys.
A surface that cannot resolve `var(--x)` (a headless SVG rasterizer, for example) should call `distillery.resolveValues(scheme, variation?)` instead of walking `themeVars` by hand. That walk returns nested literal strings for one scheme, including `ScaleToken.value`. A surface that still wants the stylesheet, but has no color scheme for `light-dark()` to resolve against, passes `{ scheme }` to `renderStyles`. See [read values outside CSS](https://docs-v3-preview.elastic.dev/distillate/guides/non-css-surfaces).
The `chip` module below uses `tokens.colors.surface` from the [quick start](https://docs-v3-preview.elastic.dev/distillate/getting-started/quick-start) token tree.

## Scale tokens

```ts
const gap = cq('8px', '2cqi');
String(gap); 
gap.cq; 
```

`cq` is an alias of `scaleToken`.

## Shared contextual vars

```ts
const foreground = contextualVar(
  'vars/app/tone/foreground',
  '--eui-app-tone-foreground'
);
String(foreground); 
String(foreground.name); 
```

Register the path in `sharedVars` so two modules can share the name without either owning it.

## Module-local `vars`

```ts
const chip = distillery.createStyleModule('chip', ({ css, tokens, vars }) => {
  const look = vars('look', {
    bg: tokens.colors.surface,
    unusedBorder: tokens.colors.accent, 
  });
  return {
    root: css`
      ${look} 
      background: ${look.bg}; 
    `,
    loud: css`
      ${look.set({ bg: tokens.colors.accent })} 
    `,
  };
});
```

Local-var names are `cssVarName(prefix, path)` (`--${prefix}-${module}-${group}-${key}`). A collision with a theme or shared var throws at module construction. See [name collisions](https://docs-v3-preview.elastic.dev/distillate/guides/name-collisions).