@cueplusplus/tokens
v0.14.1
Published
DTCG design tokens for the CUE++ design system: 5 density levels and 8 font pairings, compiled to attribute-scoped CSS custom properties. Colour lives in a theme package.
Readme
@cueplusplus/tokens
The token layer under @cueplusplus/ui, for an app that needs the vocabulary by name rather than
through a component: five density rungs × eight font pairings, authored as DTCG source and
compiled to attribute-scoped CSS custom properties.
Two of the system's three DOM axes live here, and they own strictly disjoint token sets:
| axis | owns |
| --- | --- |
| [data-density] | geometry — control heights, radii, spacing, type sizes |
| [data-font] | the three type stacks a pairing names |
Colour is not here. The third axis, [data-theme], left this package: a palette is a package
of its own now (@cueplusplus/theme-<name>, and anybody else's), so there is no THEMES export,
no ThemeName, and dist/theme.css is a deprecated alias of axes.css — kept through 0.10, and
removed in the minor after. The blank palette an unstamped page paints lives in
@cueplusplus/theme-base.
Install
The @cueplusplus scope is public on npm and resolves there by default, so there is nothing
to configure and no credential to supply — it installs like any other package.
pnpm add @cueplusplus/tokensNo peers and no dependencies: this package is generated data and eight lines of JavaScript. It
also arrives as a dependency of @cueplusplus/ui, so an app that installs the components already
has it — naming it in package.json just makes the constants importable in your own code.
CI, Vercel and the token's expiry are in
docs/CONSUMING.md §1.
Quick start
An app importing @cueplusplus/ui/styles.css already has the axes as CSS; it needs this package
by name only to stop restating what it exports.
import { DENSITIES, token } from "@cueplusplus/tokens";
const ring = `1px solid ${token("focus")}`; // "1px solid var(--cue-focus)"
const labels = DENSITIES.map((rung) => [rung, rung.replace(/-/g, " ")] as const);DENSITIES is ["ultra-compact", "compact", "normal", "large", "ultra-large"], in ladder order.
Derive a picker's labels and a stylesheet's rung list from it rather than writing either out: both
go stale silently when the ladder changes, and nothing anywhere reports it.
Without a bundler, the same thing in CSS is one import:
@import "@cueplusplus/tokens/axes.css";What it ships
| subpath | what it is |
| --- | --- |
| @cueplusplus/tokens | DENSITIES, MODES, FONTS, FONT_PAIRINGS, FONT_FACES, COLOR_CONTRACT, GEOMETRY_CONTRACT, FONT_TOKENS, the DEFAULT_* values, faceProperty() and token() |
| ./axes.css | the two axes as CSS, with no colour in them |
| ./tailwind.css | the Tailwind v4 @theme inline mapping layer |
| ./theme.css | a deprecated alias of ./axes.css: kept through 0.10, removed in the minor after |
| ./base.json | the same axes as data, for a theme built outside this build |
| ./primitives.tokens.json | the tier-1 palette a theme source aliases |
| ./registry/token-layer.json | the theme-independent half of the layer as a shadcn fragment — folded into a registry base item, not installable on its own |
The root entry is dist/tokens.js with dist/tokens.d.ts beside it — plain JavaScript, because
Node refuses to strip types for anything under node_modules and a .ts entry is one a
registry consumer cannot load.
Everything here is generated by build.mjs from src/**.tokens.json. Edit the sources, never
dist/.
Where the rest is
- Installing and using it from another project:
docs/CONSUMING.md - The density ladder, and what moves on each rung: https://ui.cueplusplus.com/docs/density
- The eight pairings, and which five your app has to deliver: https://ui.cueplusplus.com/docs/typefaces
- The
--cue-*contract and how a theme fills it: https://ui.cueplusplus.com/docs/theming - What changed in the version you have:
node_modules/@cueplusplus/tokens/CHANGELOG.md
