Design tokens are the foundation of sugarcube. They express design decisions in a platform-agnostic way that both designers and developers can understand. Following the W3C Design Token Format, sugarcube transforms these tokens into CSS variables.
Design tokens solve fundamental problems in modern product and website development:
-
Shared Language: Tokens create a common vocabulary between designers and developers. When a designer says “use the primary color,” everyone knows exactly what that means, regardless of their tool.
-
Consistency: By storing design decisions in a structured format, you ensure that colors, spacing, typography, and other design elements are used consistently across your project.
-
Future-Proofing: As new platforms and tools emerge, your design decisions remain consistent because they’re stored in a platform- and tool-agnostic format.
A W3C design token file is a JSON object that can contain both tokens and token groups. Here’s the basic structure:
{ "color": { // Token group "primary": { // Token "$value": "#0066cc", // The actual value "$type": "color", // The type of token "$description": "Primary brand color" // Optional metadata } }}
- Token groups: Objects that organize related tokens (like
color
orspacing
) - Tokens: Individual design decisions with:
$value
: The actual value of the token$type
: The type of token (required for validation)$description
: Optional documentation$extensions
: Optional custom metadata
Tokens can reference other tokens using the {group.token}
syntax:
{ "color": { "primary": { "$value": "#0066cc", "$type": "color" }, "button": { "background": { "$value": "{color.primary}", // References the primary color "$type": "color" } } }}
Token groups can specify a $type
that applies to all tokens within them:
{ "spacing": { "$type": "dimension", // All tokens in this group are dimensions "small": { "$value": { "value": 8, "unit": "px" } } }}
In sugarcube, CSS variables are automatically generated from the token path. For example:
{ "color": { "primary": { "$value": "#0066cc" } }}
Becomes:
--color-primary: #0066cc;
This means the structure of your token groups directly influences your CSS variable names. Plan your token organization accordingly!
For more details about the W3C Design Token Format structure, see the official specification.
Note: Sugarcube implements the W3C Design Token Format, which is currently in progress and subject to change. For the most up-to-date and complete specification, please refer to the official W3C documentation. All efforts are made to keep sugarcube up to date with the latest W3C specification. If you find any discrepancies, please open an issue.
Important: Sugarcube enforces strict compliance with the W3C Design Token Format. All tokens are validated against the specification during the token-to-CSS generation pipeline. This validation happens automatically, but you can also validate your tokens manually using the
validate
command.
Sugarcube supports all W3C token types, plus our own fluidDimension
type.
Type | Description | Example |
---|---|---|
color | CSS color values | "#0066cc" |
dimension | Fixed size values with units (px, rem) | { "value": 8, "unit": "px" } |
fluidDimension | Responsive size values that scale between min/max | { "min": { "value": 1, "unit": "rem" }, "max": { "value": 2, "unit": "rem" } } |
duration | Time values with units (ms, s) | { "value": 200, "unit": "ms" } |
cubicBezier | Animation timing functions defined by four control points | [0.4, 0, 0.2, 1] |
fontFamily | Font stack as string or array of strings | "Inter, sans-serif" or ["Inter", "sans-serif"] |
fontWeight | Font weight as number (1-1000) or semantic string | 400 or "normal" |
number | Numeric values without units | 1.5 |
Type | Properties | Description |
---|---|---|
typography | fontFamily fontSize fontWeight (optional)letterSpacing (optional)lineHeight (optional) | Font combinations with size, weight, and spacing |
border | color width style | Border definitions with color, width, and style |
shadow | color offsetX offsetY blur spread inset (optional) | Box shadows with position, blur, and spread |
gradient | Array of { color, position } | Color gradients defined by stops |
transition | duration delay (optional)timingFunction | Animation transitions with timing |
strokeStyle | Either predefined keywords or { dashArray, lineCap } | Line styles for borders and strokes |
Example of a composite type:
{ "typography": { "heading": { "$value": { "fontFamily": "Inter, sans-serif", "fontSize": { "value": 24, "unit": "px" }, "fontWeight": 700, "lineHeight": 1.2 }, "$type": "typography" } }}
Sugarcube extends the W3C spec with a fluidDimension
type that generates CSS clamp()
values. This allows you to define dimensions that scale between a minimum and maximum size:
{ "spacing": { "small": { "$value": { "min": { "value": 1, "unit": "rem" }, "max": { "value": 2, "unit": "rem" } }, "$type": "fluidDimension" } }}
--spacing-small: clamp(1rem, 1rem + 1vw, 2rem);
The value will fluidly scale between 1rem and 2rem based on viewport width.
The viewport width min and max can be configured in the sugarcube.config.json
file. See the configuration documentation for more details.
When working with composite tokens (like borders, shadows, and gradients), sugarcube uses a layered approach:
-
Base Properties: Individual properties defined in the token system
{"stroke": {"width": {"thin": { "$value": { "value": 1, "unit": "px" } }},"style": { "$value": "solid" },"color": {"primary": { "$value": "{color.neutral.200}" }}}} -
Component Properties: Component-specific overrides of base properties
{"card": {"stroke": {"width": { "$value": "{stroke.width.thin}" },"style": { "$value": "{stroke.style}" },"color": { "$value": "{stroke.color.primary}" }}}} -
Composition: Tokens that combine individual properties
{"border": {"card": {"$value": {"width": "{card.stroke.width}","style": "{card.stroke.style}","color": "{card.stroke.color}"}}}} -
Usage: CSS variables with fallbacks
--card-border: var(--border-card);.card {border: var(--card-border, none);}
This pattern provides flexibility while maintaining consistency:
- Individual properties can be overridden in themes
- Composed values can be overridden as a whole
- Fallbacks are handled at the usage site
All components should aim to follow this pattern:
border-radius: var(--[component]-[element]-radius, var(--[semantic]-radius, var(--[primitive]-radius, [raw-value])));
This gives you the best of both worlds: semantic consistency with design flexibility when you need it. The component-specific token becomes your “get out of jail free” card for when the semantic radius doesn’t fit the design requirements.
Sugarcube components follow a semantic token system that balances consistency with flexibility. Here’s how it works:
Components use three semantic radius categories:
--button-radius
: Interactive button-like elements (buttons, dropdown triggers, select triggers)--input-radius
: Form input elements (inputs, textareas, checkboxes, radio groups)--panel-radius
: Content containers (cards, alerts, dialogs, popovers, dropdown content)
Sugarcube generates different .tokens.json
files based on your setup:
For Starter Kit Users:
{ "dropdown": { "content": { "radius": { "$value": "{panel.radius}" }, "bg": { "$value": "{surface.primary}" }, "text": { "$value": "{text.primary}" } } }}
For Non-Starter Kit Users:
{ "dropdown": { "content": { "radius": { "$value": "0.5rem" }, "bg": { "$value": "#ffffff" }, "text": { "$value": "#000000" } } }}
Component CSS files use simple, clean variable references without complex fallback chains:
.dropdown-menu-content { border-radius: var(--dropdown-content-radius); background-color: var(--dropdown-content-bg); color: var(--dropdown-content-text); padding: var(--dropdown-content-padding);}
Why No Fallbacks?
- Tokens Are Always Provided: Sugarcube ensures that all component tokens are always available, either as semantic references or raw values
- Fail Fast: If tokens are missing, it indicates a real problem that should be fixed, not masked
- Cleaner CSS: No complex fallback chains that make CSS harder to read and maintain
- Better Debugging: Missing tokens cause clear errors rather than silent fallbacks to unexpected values
Users can customize components in multiple ways:
- Edit component tokens: Modify the
.tokens.json
file to reference your own semantic tokens - Override CSS variables: Set component-specific CSS variables in your stylesheets
- Use semantic tokens: Let components automatically inherit from your design system
- Start without starter kit: Get raw value tokens that work immediately
- Add your own tokens: Manually update component tokens to reference your semantic system
- Adopt starter kit: Component tokens automatically work with the new semantic system
When building tools or GUIs for token management, the system supports:
- Raw values: Write direct values to any token
- Semantic references: Reference other tokens in the system
- Component overrides: Override any component-specific token
- Semantic token updates: Update semantic tokens that affect multiple components
This approach provides semantic consistency by default while maintaining complete customization flexibility when needed.