@clay-design-system/tokens
Design tokens for the Clay design system, compiled from DTCG JSON sources using Style Dictionary 4.
Tier system
Tokens are organized in a layered hierarchy:
Foundation (base primitives — colors, type, spacing, radius, effects)
↓ referenced by
Semantic (purpose-driven tokens — background, text, border, icon, size, motion)
↓ referenced by
Web / Platform / Marketing (tier-specific tokens — typography scales, component tokens)
Components consume semantic or tier-specific tokens. The one raw primitive components may use is the brand palette (--clay-foundation-brand-color-*); the stylelint rule below blocks the retired colour names. Prefer semantic radius/spacing over raw --clay-foundation-radius/spacing-* (guideline, not lint-enforced).
Source structure
src/
├── foundation/ Foundation primitives
│ ├── colors.json Brand color palette → --clay-foundation-brand-color-* — exact Figma "Mode 1" stops (grey, yellow, lime, stone, harvest, orange, magenta, pink, iris, purple, blue, teal, green)
│ ├── typography.json Font families, weights, size scale
│ ├── spacing.json 18-step spacing scale (0-180)
│ ├── radius.json 10 radius values (none → full)
│ ├── effects.json Shadow + blur primitives
│ ├── stroke.json Border width + color
│ └── customer-logos.json Logo surface colors
├── semantic/ Purpose-driven tokens
│ ├── color-primitives.json Neutrals, greys, brand palette aliases
│ ├── brand.json Product colors (monday, wm, crm, dev, svc)
│ ├── text.json 7 text color variants
│ ├── icon.json 7 icon color variants
│ ├── background.json 8 background variants + utilities
│ ├── border.json 9 border color variants
│ ├── size.json Space scale, icon sizes, depth
│ ├── radius.json Layout/card radius scale + aliases
│ ├── layout.json Container, grid, section, header, footer
│ ├── effects.json Shadows, glass, device-frame
│ ├── motion.json Duration, easing, transitions
│ └── breakpoints.json Responsive breakpoints
├── web/ Web tier (marketing surfaces)
│ ├── typography.json 40 text styles (desktop + mobile)
│ ├── button.json Button: 4 sizes × 4 styles × 4 colors
│ ├── card.json Card: container, image, size scale
│ ├── input.json Input: colors, sizes, states
│ ├── toggle.json Toggle: track, thumb
│ ├── checkbox.json Checkbox: control, group, square
│ ├── tag.json Tag: background + dot variants
│ ├── tabs.json Tabs: triggers, panels, shells
│ └── slider.json Slider: dots + arrows
├── platform/ Platform tier (product UI)
│ └── typography.json 11 text styles (headlines, labels, captions)
├── marketing/ Marketing tier (campaigns)
│ └── customer-logos.json Logo height + surface colors
└── email/ Email tier (read by @clay-design-system/email at build time)
└── typography.json Lifecycle email type scale
Output
pnpm --filter @clay-design-system/tokens build (src/build.ts) writes:
dist/tokens.css(@clay-design-system/tokens/css) — every tier as CSS custom properties on:root; aliases stayvar()so changes cascadedist/tokens.resolved.css(@clay-design-system/tokens/css-resolved) — the same with literal valuesdist/tokens.js+.d.ts(@clay-design-system/tokens) — JS constants (used by@clay-design-system/email);dist/index.cjs+.d.ctsforrequire()dist/mq.js/mq.cjs(@clay-design-system/tokens/mq) —mq/breakpointsmedia-query helpers, ESM and CJSdist/TOKEN_REFERENCE.md— a generated listing of every token
Usage
// In your app entry point:
import '@clay-design-system/tokens/css'
// In component CSS:
.card {
border-radius: calc(var(--clay-card-radius-value) * 1px);
padding: calc(var(--clay-card-padding-value) * 1px);
background: var(--clay-card-background);
}
Naming convention
--clay-{tier?}-{category}-{variant?}-{property}
- Foundation:
--clay-foundation-brand-color-iris-300,--clay-foundation-type-weight-medium - Semantic:
--clay-color-background-brand-default,--clay-size-space-400,--clay-motion-duration-fast - Web:
--clay-web-type-large-desktop-size,--clay-btn-primary-black-bg - Platform:
--clay-platform-type-headline-xl-600-size - Component:
--clay-card-radius,--clay-input-border-color,--clay-tabs-trigger-font-size
Adding or modifying tokens
- Edit or create a
.jsonfile insrc/{tier}/ - Use DTCG format:
{ "$value": ..., "$type": "..." } - Reference other tokens with
{clay.path.to.token}syntax - Run
pnpm build— verifydist/tokens.cssupdated - Check
dist/TOKEN_REFERENCE.mdfor the generated output
Enforcement
The stylelint plugin @clay-design-system/tokens/stylelint-plugin/no-foundation-tokens.js (run by pnpm --filter @clay-design-system/react lint) blocks the retired colour names — --clay-foundation-color-*, --clay-web-color-*, --clay-brand-color-*. It polices the colour layer only.
{
"plugins": ["@clay-design-system/tokens/stylelint-plugin/no-foundation-tokens.js"],
"rules": { "clay-ds/no-foundation-tokens": true }
}
Unitless values
Most numeric tokens are unitless. In CSS, multiply by 1px:
padding: calc(var(--clay-size-space-400) * 1px); /* → 16px */
This allows tokens to be used in calculations without unit conflicts.
Agent-facing token guide (heading tiers, naming, usage rules): skills/web-design-brain/reference/TOKENS.md.