Design Tokens

The foundational token system that powers all visual consistency across Byteion components.

Overview

Design tokens are the atomic values that power every visual aspect of Byteion. They are the single source of truth for colors, spacing, typography, shadows, borders, and motion. Instead of hardcoding values like #3b82f6 or 0.5rem, components reference semantic tokens like bg-primary and spacing values like p-md. This ensures visual consistency across every screen and enables systematic re-theming without touching component markup.

Why this exists

Without tokens, changing a brand color requires searching for every occurrence of bg-blue-500 and text-blue-600 across 50+ components. With tokens, you change one CSS variable (--primary) and every component that references it updates simultaneously. This is not just about efficiency — it ensures that the entire system responds to a change in a predictable, consistent way. Tokens also create a shared vocabulary between designers and developers: when a designer says "use the primary color", the developer reaches for bg-primary, not bg-blue-500.

System philosophy

Consistency rules

  • Prefer semantic tokens in components. Shared component styling should use Byteion tokens for visual decisions such as color, spacing, radius, shadow, typography, and motion. Structural Tailwind utilities are allowed when they describe layout behavior rather than brand or design values.
  • Semantic naming. Tokens describe purpose, not appearance. Use bg-background not bg-white, text-foreground not text-gray-900.
  • Scale-based values. When a token is not available, add it to the scale before using arbitrary values in shared components.

Scaling logic

Tokens are organized in scales that grow predictably. The spacing scale follows 0.25rem increments. Color scales (50-950) are designed to support accessible foreground/background combinations. Semantic foreground/background pairs should be tested for sufficient contrast, especially after custom theme overrides.

Shared vocabulary

Tokens create a vocabulary that designers and developers share. When a designer says "use the primary color", the developer knows exactly which token to use (bg-primary). When a developer needs a subtle border, they reach for border-border. This shared language eliminates interpretation errors and ensures consistent implementation.

Token layers

Tokens exist in three layers, each serving a distinct role:

LayerFilePurpose
JS tokenspackages/tokens/*.jsBuild-time source of truth — defines scales, defaults, and the shape of the design system
CSS variablespackages/core/theme/variables.cssRuntime theming layer — override at the CSS level for white-label or multi-brand themes
Tailwind presetpackages/core/tailwind.preset.cjsMaps tokens into utility classes (bg-background, shadow-card, rounded-button)

Token types

Byteion defines three categories of tokens, each with a different purpose and audience:

Primitive / scale tokens

Raw values organized in steps. Used to build the system and define new semantic aliases.

  • primary-50 through primary-950
  • spacing-sm, spacing-md, spacing-lg
  • shadow-sm, shadow-xs
  • Utility: bg-primary-500, p-4

Semantic tokens

Named by purpose, not value. Used in components and application UI for consistent theming.

  • bg-primary, text-primary-foreground
  • bg-background, bg-card
  • border-border, ring-ring
  • text-muted-foreground

Component tokens

Target specific component families. Keeps radii, shadows, and spacing consistent per component type.

  • rounded-button, rounded-card
  • shadow-card, shadow-dropdown
  • shadow-button, shadow-button-hover
  • p-inset-sm, gap-stack-md

Naming system

Tokens follow a consistent naming pattern:

property-variant-modifier
  • bg-primary — Semantic background (brand color)
  • text-muted-foreground — Muted text color (semantic)
  • border-border — Border color (semantic)
  • rounded-card — Card border radius (component token)
  • bg-primary-500 — Primary at scale step 500 (primitive)
  • p-md — Medium padding from spacing scale

Categories

Colors

Controls surface backgrounds, text, borders, focus rings, and brand accents. Every component uses color tokens for its visual state.

  • bg-background, text-foreground — Page surface
  • bg-card, text-card-foreground — Card surfaces
  • bg-primary, text-primary-foreground — Brand actions
  • border-border, ring-ring — Chrome

Spacing

Controls padding, margin, gap, and layout density. Used by every component's internal and external spacing.

  • p-inset-sm — Button / input padding
  • gap-stack-md — Vertical spacing between items
  • p-surface-card — Card inner padding

Radius

Controls corner rounding per component family. Each component has a dedicated token.

  • rounded-button (0.5rem) — Buttons
  • rounded-card (0.75rem) — Cards, panels
  • rounded-input (0.5rem) — Inputs, selects
  • rounded-badge (9999px) — Badges, pills, tags

Shadows

Controls elevation and interactive state feedback. Component-specific tokens target the right context.

  • shadow-card — Default card elevation
  • shadow-button — Button default / hover
  • shadow-dropdown — Menu / popover surfaces
  • shadow-modal — Modal / dialog elevation

Typography

Controls font family, size, weight, line height, and letter spacing across headings, body text, and code.

  • font-sans (Inter) — Product UI
  • font-mono (JetBrains Mono) — Code
  • text-sm, text-base, text-lg — Size scale
  • font-medium, font-semibold, font-bold — Weights

Motion

Controls transition durations and easing curves for interactions, animations, and micro-interactions.

  • duration-fast (120ms) — Hover states
  • duration-normal (200ms) — Default transitions
  • ease-out-soft — Entry animations
  • ease-spring — Scale / pop effects

Practical usage

Developers use tokens through Tailwind utility classes. Always prefer semantic and component tokens over raw scale steps in shared components:

<!-- Button using semantic tokens -->
<button class="inline-flex items-center gap-2 rounded-button bg-primary px-md py-sm text-primary-foreground shadow-button hover:bg-primary/90">
  Save changes
</button>

<!-- Card using surface and component tokens -->
<div class="rounded-card border border-border bg-card shadow-card">
  <div class="p-surface-card">
    <h3 class="font-semibold text-foreground">Card title</h3>
    <p class="text-muted-foreground mt-2">Card body content goes here.</p>
  </div>
</div>

<!-- Badge using component tokens -->
<span class="inline-flex items-center rounded-badge bg-primary/10 px-inset-xs py-0.5 text-xs font-medium text-primary">
  Active
</span>

Behind the scenes

Each utility class is backed by a CSS variable. The / <alpha-value> syntax enables Tailwind's opacity modifier (bg-primary/50):

/* Semantic color mapping */
.bg-primary {
  background-color: hsl(var(--primary) / <alpha-value>);
}
.text-primary-foreground {
  color: hsl(var(--primary-foreground) / <alpha-value>);
}
.bg-card {
  background-color: hsl(var(--card) / <alpha-value>);
}

/* Component token mapping */
.rounded-card {
  border-radius: var(--radius-card);
}
.shadow-card {
  box-shadow: var(--shadow-card);
}
.rounded-button {
  border-radius: var(--radius-button);
}

/* Spacing mapping */
.px-md {
  padding-left: var(--spacing-md, 1rem);
  padding-right: var(--spacing-md, 1rem);
}

Color CSS variables store raw HSL channel values (hue saturation% lightness%) without the hsl() wrapper. This is required for Tailwind's alpha-value syntax:

:root {
  /* Correct — raw HSL channels enable bg-primary/50 */
  --primary: 217 91% 60%;
  --primary-foreground: 0 0% 100%;

  /* Component tokens store full values */
  --radius-card: 0.75rem;
  --shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.04), 0 1px 2px -1px rgb(0 0 0 / 0.04);
}

Semantic vs scale tokens

Choosing the right token type depends on context:

Use semantic tokens when

  • Building shared components (bg-primary, text-foreground)
  • Writing application UI that should theme automatically
  • Referencing component-specific values (rounded-card, shadow-button)
  • Setting surface, text, border, and ring colors in layouts

Use scale tokens when

  • Defining the design language or creating new semantic aliases
  • Building charts, data visualizations, or custom graphics
  • Extending the system with new component tokens
  • Applying a specific scale step with a clear rationale

Avoid using raw scale steps (e.g. bg-primary-500) everywhere in application UI unless the purpose is clear. Prefer bg-primary so that a brand theme override of --primary flows through automatically.

Do and Don't

Do

  • Use semantic tokens in shared components (bg-background, text-foreground)
  • Use component-specific radii and shadows (rounded-button, shadow-card)
  • Use spacing tokens from the scale (p-inset-sm, gap-stack-md)
  • Use bg-primary instead of bg-primary-500 in UI components
  • Refer to the token reference when uncertain about a value

Don't

  • Use arbitrary values (bg-[#3b82f6], p-[13px]) in shared components
  • Use raw Tailwind color steps (bg-blue-500) — use semantic tokens instead
  • Create new spacing values without first checking the token scale
  • Use text-white when text-primary-foreground is the correct semantic token
  • Mix primitive and semantic tokens in the same component without purpose

Customization

Override tokens by redefining CSS variables in your project. This is the recommended approach for white-label theming because it requires no component markup changes:

/* Override semantic tokens for a white-label theme */
:root {
  --primary: 270 100% 50%;
  --primary-foreground: 0 0% 100%;
  --radius-card: 0.75rem;
  --shadow-card: 0 4px 12px rgb(0 0 0 / 0.08);
}

Each layer serves a different customization scenario:

  • CSS variables — Runtime customization. Change at the :root level for immediate visual updates. Best for multi-brand or white-label themes.
  • JS tokens — Build-time source. Edit the token files in packages/tokens/ when you need to change the foundation of the system.
  • Tailwind preset — Maps both into utility classes. Extend the preset to add new tokens or override existing mappings.

To add entirely new tokens, extend the Tailwind preset:

const byteionPreset = require('@byteion/core/preset');

module.exports = {
  presets: [byteionPreset],
  theme: {
    extend: {
      colors: {
        brand: {
          50: '#eff6ff',
          500: '#3b82f6',
          900: '#1e3a8a',
        },
      },
    },
  },
};

For advanced multi-brand theme setup, see the Theming Guide.

Relationship to components

Every Byteion component uses tokens internally. Components never hardcode values — they reference semantic and component tokens throughout:

Button

  • bg-primary — Primary variant background
  • text-primary-foreground — Text on primary
  • rounded-button — Border radius
  • px-md py-sm — Padding
  • shadow-button — Default shadow
  • hover:shadow-button-hover — Hover shadow

Card

  • bg-card — Card surface
  • text-card-foreground — Card text
  • border-border — Card border
  • rounded-card — Border radius
  • shadow-card — Elevation

When you change a token, every component that uses it updates. Change --primary and all primary buttons, links, focus rings, and active indicators update simultaneously. Change --radius-card and every card across the application adopts the new rounding — no markup changes needed.

Token dependency tree

CSS Variables (runtime)
← Tailwind preset maps to utility classes
← Components use utility classes
← Apps compose components

Developer tips

• Tokens are HSL. All color variables store raw HSL channels to enable Tailwind's alpha syntax (bg-primary/50). Never store hex values in CSS variables. • Use semantic names. When you see bg-white, replace it with bg-background — it adapts to dark mode automatically. • Semantic tokens survive rebranding. A component using bg-primary responds to a --primary variable change. A component using bg-primary-500 requires a preset rebuild. • Check the reference. Before creating a new color or spacing value, verify it does not already exist in the token system. • Use bg-primary over bg-primary-500. The semantic alias follows brand theme overrides; the scale step does not.

Common mistakes

  • Using bg-blue-500 in shared components. This hardcodes a Tailwind color that ignores your brand overrides. Use bg-primary instead.
  • Using text-white on primary buttons. In dark mode or with a custom brand, text-white may lack contrast. Use text-primary-foreground.
  • Editing component markup instead of tokens. If you need rounded cards, change --radius-card in CSS, not the rounded-* class on every card instance.
  • Creating one-off spacing values. Adding p-[13px] breaks the spacing rhythm. Use the existing scale or propose a new token.
  • Mixing primitive and semantic tokens without purpose. A component that uses both bg-background and bg-primary-500 may behave inconsistently when themes change.
  • Forgetting dark mode variables. Custom CSS variable overrides should be mirrored in a .dark or [data-theme="dark"] block unless the value is mode-agnostic.

Production usage tips

  • Test dark mode after token changes. Every --background and --foreground override needs a corresponding dark-mode value to maintain readability.
  • Test brand themes after overriding CSS variables. Verify that all components that use bg-primary, text-primary-foreground, and border-primary reflect the new values.
  • Run contrast checks. After changing foreground/background pairs, test WCAG contrast ratios. Tools like the WebAIM contrast checker can validate your combinations.
  • Keep framework examples aligned. React and Vue components use the same token classes as HTML. The utility classes are framework-agnostic.
  • Avoid primitive color utilities in shared source. Importing bg-primary-500 in a component library may bypass theme overrides. Stick to semantic aliases in shared code.

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced component patterns.

Explore Pro Components