Frontfriend

Design Tokens

Understanding Frontfriend's semantic token system for consistent design

Design Tokens

Frontfriend uses a semantic token system that provides meaningful, intent-based design tokens instead of traditional color-based utilities. This approach ensures consistency, scalability, and automatic theming support.

Why Semantic Tokens?

A semantic token is an abstraction layer that helps define design decisions in a meaningful way rather than relying on raw, primitive values. Instead of using direct values like #ff0000 for red or 16px for padding, semantic tokens assign intent-driven names that reflect their purpose in the UI.

Key Benefits

  • Meaningful Names - bg-brand-strong is more descriptive than bg-blue-500
  • Automatic Theming - Light and dark modes work automatically
  • Design Consistency - Tokens come directly from your Figma design system
  • Scalability - Changes in design propagate across all applications
  • Maintainability - Update tokens centrally, not in every component

Important: Do NOT use traditional Tailwind color classes like bg-blue-500, text-red-600, or border-green-400. Always use semantic token classes instead.

Token System Overview

Frontfriend's token system is organized into several categories:

  1. Semantic Colors - Intent-based colors (brand, neutral, positive, negative, etc.)
  2. Layer Tokens - Elevation and surface hierarchy
  3. Overlay Tokens - Background overlays for dialogs and modals
  4. Typography Tokens - Text size and style scales
  5. Interaction States - Hover and active states

Semantic Colors

The 9 Intents

Our design system defines 9 different semantic intents, each representing a distinct purpose:

  1. Neutral - Default elements without strong emphasis (grays)
  2. Brand - Brand-specific elements (primary color)
  3. Inverse - Inverted neutral scale for contrast
  4. Positive - Positive actions, confirmations, success states (green)
  5. Warning - Alerts and cautionary indicators (orange/yellow)
  6. Negative - Errors and destructive actions (red)
  7. Informative - Informational elements (blue)
  8. Highlight - High prominent elements (accent colors)
  9. Interactive - Default interactive element colors

Intensity Levels

Each semantic color has four intensity levels for creating visual hierarchy:

  • strong - Highest contrast/saturation (primary emphasis)
  • mid - Medium contrast/saturation (standard use)
  • subtle - Low contrast/saturation (secondary elements)
  • low - Lowest contrast/saturation (backgrounds)

Background Classes

/* Neutral backgrounds */
bg-neutral-strong    /* High contrast neutral */
bg-neutral-mid       /* Standard neutral */
bg-neutral-subtle    /* Subtle neutral */
bg-neutral-low       /* Very light neutral */
 
/* Brand backgrounds */
bg-brand-strong      /* Strong brand color */
bg-brand-mid         /* Primary brand color */
bg-brand-subtle      /* Subtle brand tint */
bg-brand-low         /* Very light brand tint */
 
/* Status backgrounds */
bg-positive-mid      /* Success/confirmation green */
bg-negative-mid      /* Error/danger red */
bg-warning-mid       /* Warning orange/yellow */
bg-info-mid          /* Information blue */
bg-highlight-mid     /* Accent/emphasis color */

Text Classes

/* Neutral text - for body content */
text-neutral-strong   /* Headings and primary text */
text-neutral-mid      /* Body text */
text-neutral-subtle   /* Secondary text */
text-neutral-low      /* Tertiary/helper text */
 
/* Brand text */
text-brand-strong
text-brand-mid
text-brand-subtle
 
/* Status text */
text-positive-mid     /* Success messages */
text-negative-mid     /* Error messages */
text-warning-mid      /* Warning messages */
text-info-mid         /* Info messages */
 
/* Inverse text (on dark backgrounds) */
text-inverse-strong
text-inverse-mid
text-inverse-subtle
text-inverse-low
 
/* Disabled state */
text-disabled

On-Color Text (Contrast Text)

For text that appears on colored backgrounds with proper contrast:

/* Text on brand backgrounds */
text-onbrand-strong
text-onbrand-mid
text-onbrand-subtle
text-onbrand-low
 
/* Text on positive/success backgrounds */
text-onpositive-strong
text-onpositive-mid
text-onpositive-subtle
text-onpositive-low
 
/* Text on negative/error backgrounds */
text-onnegative-strong
text-onnegative-mid
text-onnegative-subtle
text-onnegative-low
 
/* Text on warning backgrounds */
text-onwarning-strong
text-onwarning-mid
text-onwarning-subtle
text-onwarning-low
 
/* Text on info backgrounds */
text-oninfo-strong
text-oninfo-mid
text-oninfo-subtle
text-oninfo-low

Border Classes

/* Neutral borders */
border-neutral-strong
border-neutral-mid
border-neutral-subtle
border-neutral-low
 
/* Brand borders */
border-brand-strong
border-brand-mid
border-brand-subtle
 
/* Status borders */
border-positive-mid
border-negative-mid
border-warning-mid
border-info-mid
 
/* Disabled state */
border-disabled

Interaction States

Interactive elements support hover and active states:

/* Background interactions */
bg-neutral-subtle-hover
bg-neutral-subtle-active
bg-brand-mid-hover
bg-brand-mid-active
 
/* Text interactions */
text-brand-mid-hover
text-brand-mid-active
 
/* Border interactions */
border-neutral-subtle-hover
border-brand-mid-hover

Layer Tokens

Layer tokens define the elevation hierarchy of UI surfaces. They determine how elements visually stack and interact with each other, creating depth and organization.

The 6 Layer Levels

bg-layer-below       /* Lowest background layer (page background) */
bg-layer-surface     /* Main content surface (cards, panels) */
bg-layer-raised      /* Elevated content (floating cards) */
bg-layer-popover     /* Popover/dropdown backgrounds */
bg-layer-dialog      /* Modal/dialog backgrounds */
bg-layer-control     /* Form control backgrounds (inputs) */

Layer Usage Guide

LayerPurposeExample Use Cases
layer-belowPage backgroundApp background, body
layer-surfaceContent containersMain cards, sections
layer-raisedElevated elementsFeatured cards, hovering menus
layer-popoverFloating UIDropdowns, tooltips, popovers
layer-dialogModalsDialogs, sheets, overlays
layer-controlForm inputsText inputs, selects, textareas

Overlay Tokens

Overlay tokens are used for semi-transparent backgrounds, typically for dialogs, modals, or drawer overlays:

overlay-strong       /* High opacity overlay (75-90%) */
overlay-mid          /* Medium opacity overlay (50-65%) */
overlay-subtle       /* Low opacity overlay (25-40%) */
overlay-low          /* Very low opacity overlay (10-20%) */

Overlay Usage

{/* Modal backdrop */}
<div className="fixed inset-0 overlay-mid">
  <div className="bg-layer-dialog rounded-lg">
    {/* Modal content */}
  </div>
</div>

Typography Tokens

Typography tokens provide a consistent text size scale across your application. Frontfriend uses Tailwind's font-size utilities for typography.

Text Size Classes

text-xs     /* Extra small text - 0.75rem (12px) */
text-sm     /* Small text - 0.875rem (14px) */
text-base   /* Base/body text - 1rem (16px) */
text-lg     /* Large text - 1.125rem (18px) */
text-xl     /* Extra large text - 1.25rem (20px) */
text-2xl    /* 2X large text - 1.5rem (24px) */
text-3xl    /* 3X large text - 1.875rem (30px) */
text-4xl    /* 4X large text - 2.25rem (36px) */
text-5xl    /* 5X large text - 3rem (48px) */
text-6xl    /* 6X large text - 3.75rem (60px) */
text-7xl    /* 7X large text - 4.5rem (72px) */
text-8xl    /* 8X large text - 6rem (96px) */
text-9xl    /* 9X large text - 8rem (128px) */

These work with standard Tailwind typography utilities and integrate seamlessly with semantic color tokens.


Common Usage Patterns

Card Component

<div className="bg-layer-surface border border-neutral-subtle rounded-lg p-4">
  <h3 className="text-neutral-strong text-lg font-semibold">
    Card Title
  </h3>
  <p className="text-neutral-mid mt-2">
    Card content with proper semantic colors.
  </p>
</div>

Button Components

{/* Primary button */}
<button className="bg-brand-mid hover:bg-brand-mid-hover text-onbrand-mid px-4 py-2 rounded">
  Save Changes
</button>
 
{/* Secondary button */}
<button className="bg-neutral-subtle hover:bg-neutral-subtle-hover text-neutral-strong px-4 py-2 rounded">
  Cancel
</button>
 
{/* Destructive button */}
<button className="bg-negative-mid hover:bg-negative-mid-hover text-onnegative-mid px-4 py-2 rounded">
  Delete
</button>

Form Input

<input
  type="text"
  className="bg-layer-control border border-neutral-subtle text-neutral-mid placeholder:text-neutral-subtle px-3 py-2 rounded focus:border-brand-mid"
  placeholder="Enter your email..."
/>

Alert Messages

{/* Success alert */}
<div className="bg-positive-low border border-positive-mid rounded p-3">
  <p className="text-positive-strong">
    Success! Your changes have been saved.
  </p>
</div>
 
{/* Error alert */}
<div className="bg-negative-low border border-negative-mid rounded p-3">
  <p className="text-negative-strong">
    Error! Something went wrong.
  </p>
</div>
 
{/* Warning alert */}
<div className="bg-warning-low border border-warning-mid rounded p-3">
  <p className="text-warning-strong">
    Warning! This action cannot be undone.
  </p>
</div>
 
{/* Info alert */}
<div className="bg-info-low border border-info-mid rounded p-3">
  <p className="text-info-strong">
    Info: New features are available.
  </p>
</div>

Page Layout

<div className="bg-layer-below min-h-screen">
  {/* Navigation */}
  <nav className="bg-layer-surface border-b border-neutral-subtle">
    <div className="container mx-auto px-6 py-4">
      {/* Nav content */}
    </div>
  </nav>
 
  {/* Main content */}
  <main className="container mx-auto p-6">
    <div className="bg-layer-raised p-6 rounded-lg">
      <h1 className="text-neutral-strong text-3xl font-bold">
        Page Title
      </h1>
      <p className="text-neutral-mid mt-2">
        Page content goes here...
      </p>
    </div>
  </main>
</div>
{/* Backdrop overlay */}
<div className="fixed inset-0 overlay-mid flex items-center justify-center">
  {/* Dialog */}
  <div className="bg-layer-dialog border border-neutral-subtle rounded-lg p-6 max-w-md w-full">
    <h2 className="text-neutral-strong text-xl font-semibold">
      Confirm Action
    </h2>
    <p className="text-neutral-mid mt-2">
      Are you sure you want to proceed?
    </p>
    <div className="flex gap-3 mt-4">
      <button className="bg-brand-mid hover:bg-brand-mid-hover text-onbrand-mid px-4 py-2 rounded">
        Confirm
      </button>
      <button className="bg-neutral-subtle hover:bg-neutral-subtle-hover text-neutral-strong px-4 py-2 rounded">
        Cancel
      </button>
    </div>
  </div>
</div>

Dark Mode Support

One of the key advantages of semantic tokens is automatic dark mode support. The same semantic classes work in both light and dark modes without any additional code:

{/* This automatically adapts to light/dark mode */}
<div className="bg-layer-surface text-neutral-mid border border-neutral-subtle">
  Content that works perfectly in both themes
</div>

The token values automatically switch based on the user's theme preference, ensuring proper contrast and readability in all scenarios.


Icon Classes

SVG Fill Colors

For coloring SVG icons using the fill attribute:

fill-icon-neutral-strong
fill-icon-neutral-mid
fill-icon-neutral-subtle
fill-icon-brand-mid
fill-icon-positive-mid
fill-icon-negative-mid
fill-icon-disabled

Icon Text Colors

For icon fonts or text-based icons:

text-icon-neutral-strong
text-icon-neutral-mid
text-icon-brand-mid
text-icon-disabled

Icon Usage

{/* SVG icon with fill */}
<svg className="fill-icon-neutral-mid w-5 h-5">
  <path d="..." />
</svg>
 
{/* Icon font */}
<i className="text-icon-brand-mid text-xl" />

Migration from Traditional Tailwind

When converting existing code from traditional Tailwind to Frontfriend semantic tokens:

Traditional TailwindFrontfriend SemanticPurpose
bg-whitebg-layer-surfaceMain surface background
bg-gray-50bg-neutral-lowVery subtle background
bg-gray-100bg-neutral-subtleSubtle background
bg-gray-900bg-neutral-strongStrong neutral background
text-gray-900text-neutral-strongPrimary text/headings
text-gray-600text-neutral-midBody text
text-gray-400text-neutral-subtleSecondary text
bg-blue-500bg-brand-midPrimary brand color
text-blue-600text-brand-midBrand text
border-gray-200border-neutral-subtleSubtle borders
bg-red-50bg-negative-lowError background
text-red-600text-negative-midError text
bg-green-50bg-positive-lowSuccess background
text-green-600text-positive-midSuccess text
bg-yellow-50bg-warning-lowWarning background
text-yellow-600text-warning-midWarning text

Best Practices

1. Always Use Semantic Classes

Use semantic tokens that describe intent, not appearance:

// ✅ Good - describes intent
<button className="bg-brand-mid text-onbrand-mid">Submit</button>
 
// ❌ Bad - describes color
<button className="bg-blue-500 text-white">Submit</button>

2. Choose Appropriate Intensity

Select the right intensity level for visual hierarchy:

<div>
  <h1 className="text-neutral-strong">Main Heading</h1>
  <p className="text-neutral-mid">Body paragraph</p>
  <span className="text-neutral-subtle">Helper text</span>
</div>

3. Use Layer Tokens for Elevation

Build proper elevation hierarchy with layer tokens:

<div className="bg-layer-below">
  <div className="bg-layer-surface">
    <div className="bg-layer-raised">
      {/* Progressively elevated content */}
    </div>
  </div>
</div>

4. Consider Interaction States

Always provide hover and active states for interactive elements:

<button className="bg-brand-mid hover:bg-brand-mid-hover active:bg-brand-mid-active">
  Click me
</button>

5. Use On-Color Text for Contrast

When placing text on colored backgrounds, use on-color variants with appropriate intensity:

<div className="bg-brand-mid text-onbrand-mid">
  Proper contrast text on brand background
</div>
 
<div className="bg-positive-mid text-onpositive-strong">
  Success message with strong contrast
</div>

6. Never Hardcode Colors

All colors should come from the design system:

// ✅ Good - uses tokens
<div className="bg-brand-mid" />
 
// ❌ Bad - hardcoded color
<div style={{ backgroundColor: '#3b82f6' }} />

Next Steps