Skip to content

Semantic Design Tokens

SisterShield uses a semantic token system that maps meaning to color, not color to component. Tokens are defined as CSS custom properties in HSL, wired through Tailwind CSS configuration, and consumed by shadcn/ui components and custom UI.

Token Architecture

The pipeline flows in three stages:

  1. CSS Custom Properties (src/app/globals.css) — define raw HSL values for light and dark mode.
  2. Tailwind Config (tailwind.config.ts) — map properties to named utility classes via hsl(var(--token)).
  3. Component Usage — components reference Tailwind classes (bg-primary, text-safety-exit, border-brand-soft-border).

This separation means a single token change in globals.css propagates to every component that uses it without touching component code.

Token Categories

Core Neutrals

TokenLight Value (HSL)Dark Value (HSL)Purpose
--background0 0% 100%222.2 84% 4.9%Page background
--foreground222.2 84% 4.9%210 20% 98%Primary text
--card0 0% 100%222.2 84% 4.9%Card surfaces
--card-foreground222.2 84% 4.9%210 20% 98%Card text
--popover0 0% 100%222.2 84% 4.9%Popover/dropdown surfaces
--popover-foreground222.2 84% 4.9%210 20% 98%Popover text
--muted210 40% 96.1%217.2 32.6% 17.5%Muted backgrounds
--muted-foreground215.4 16.3% 46.9%215 20.2% 65.1%Secondary/muted text
--secondary210 40% 96.1%217.2 32.6% 17.5%Secondary surfaces
--secondary-foreground222.2 47.4% 11.2%210 20% 98%Secondary text
--border214.3 31.8% 91.4%217.2 32.6% 17.5%Default borders
--input214.3 31.8% 91.4%217.2 32.6% 17.5%Input borders
--accent210 40% 96.1%217.2 32.6% 17.5%Accent surfaces
--accent-foreground222.2 47.4% 11.2%210 20% 98%Accent text

Brand Accent (Purple — restricted use)

TokenLight ValueDark ValuePurpose
--primary262.1 83.3% 57.8%263.4 70% 50.4%Primary CTA buttons, active focus rings
--primary-foreground210 20% 98%210 20% 98%Text on primary surfaces
--ring262.1 83.3% 57.8%263.4 70% 50.4%Focus ring color (matches primary)

Brand Soft (Light purple tints)

TokenLight ValueDark ValuePurpose
--brand-soft270 100% 98%270 30% 12%Chip backgrounds, sidebar highlights, selected states
--brand-soft-border269 97% 85%269 40% 30%Borders on brand-soft surfaces

Progress

TokenLight ValueDark ValuePurpose
--progress-fill215 14% 72%215 14% 45%Progress bar fill (in progress — neutral gray)
--progress-fill-complete142 71% 45%142 71% 35%Progress bar fill (completed — green)

Safety

TokenLight ValueDark ValuePurpose
--safety-exit0 84.2% 60.2%0 62.8% 30.6%Quick Exit button text and hover background (red)
--safety-exit-border0 72% 51%0 62.8% 40%Quick Exit button border

Destructive

TokenLight ValueDark ValuePurpose
--destructive0 84.2% 60.2%0 62.8% 30.6%Destructive actions (delete, reject)
--destructive-foreground210 20% 98%210 20% 98%Text on destructive surfaces

State-Based CTA Styling

Course cards and action buttons use different visual treatments based on the student’s completion status. This prevents “purple everywhere” and gives each state a distinct meaning.

StateCompletion StatusButton VariantVisual Treatment
ContinueIN_PROGRESSSolid primarySolid purple background, white text. This is the only solid purple button.
StartNOT_STARTEDOutline with primary borderPurple border, purple text, transparent background.
ReviewCOMPLETEDOutline with green tintGreen border, green text, transparent background.

Why This Matters

Purple is the brand accent color. If every button were solid purple, the design would lose hierarchy and the primary CTA would not stand out. By reserving solid purple for the single highest-priority action (“Continue where you left off”), the design creates a clear visual hierarchy.

Component Token Usage

ComponentTokens UsedNotes
Page backgroundbackground, foregroundApplied via body base styles
Cardscard, card-foreground, borderStandard card surfaces
Primary buttonsprimary, primary-foregroundSolid purple, reserved for primary CTA
Secondary buttonssecondary, secondary-foregroundNeutral gray buttons
Sidebar highlightsbrand-soft, brand-soft-borderActive nav items, selected chips
Progress barsprogress-fill, progress-fill-completeGray while in progress, green when done
Quick Exitsafety-exit, safety-exit-borderRed themed for urgency
Get Helpbrand-soft, brand-soft-borderRegion selector uses soft brand tokens
Destructive actionsdestructive, destructive-foregroundDelete, reject buttons
Focus ringsringMatches primary for keyboard accessibility
Input fieldsinput, borderStandard input borders

Anti-Creep Rules

To maintain the intentional design hierarchy, follow these rules:

  1. Solid purple (bg-primary) is only for the single highest-priority CTA on a page. Do not add solid purple to secondary actions, nav links, or decorative elements.
  2. Use brand-soft for selected/active states, not primary. Sidebar highlights, chips, and toggles should use the soft tint, not solid purple.
  3. Progress indicators use neutral gray (progress-fill) while in progress. Purple would falsely suggest completion or urgency.
  4. Safety components use red (safety-exit), never purple. The Quick Exit must be visually distinct from all other UI elements.
  5. New components default to neutral tokens (secondary, muted, border). Only promote to primary or brand-soft with intentional design justification.

Dark Mode

Dark mode tokens are defined in the .dark CSS class block in globals.css. Tailwind’s darkMode: ['class'] configuration means dark mode is toggled by adding the dark class to the <html> element.

Key dark mode adjustments:

  • Background inverts from white to near-black (222.2 84% 4.9%).
  • Primary purple shifts slightly darker (263.4 70% 50.4%) for reduced glare.
  • Brand-soft shifts from a near-white tint (270 100% 98%) to a dark tint (270 30% 12%).
  • Progress and safety tokens reduce saturation for comfortable contrast on dark backgrounds.

Technical Rationale

  • Scalability: Adding a new semantic meaning (e.g., “warning”) requires adding one token to globals.css and one mapping in tailwind.config.ts. No component changes needed.
  • Maintainability: Changing the brand color from purple to blue requires updating only the --primary and --ring HSL values. All components update automatically.
  • Meaning-to-color mapping: Tokens encode intent (safety-exit, progress-fill-complete), not appearance (red-500, green-400). This makes the design system self-documenting and prevents arbitrary color choices.