Skip to main content

Dark Mode

Guidelines for implementing dark mode across Juniro's platforms.


Color Mapping

When designing for dark mode, colors shift to maintain contrast and readability:

Light Mode

bg-white
bg-gray-50
bg-gray-100
text-gray-900

Dark Mode

dark:bg-gray-900
dark:bg-gray-800
dark:bg-gray-700
dark:text-gray-100

Background Mappings

Light ModeDark ModeUsage
bg-whitedark:bg-gray-900Page backgrounds
bg-gray-50dark:bg-gray-800Card backgrounds
bg-gray-100dark:bg-gray-700Secondary surfaces
bg-orange-50dark:bg-orange-900/20Brand highlights

Text Color Mappings

Light ModeDark ModeUsage
text-gray-900dark:text-gray-100Primary text
text-gray-600dark:text-gray-300Secondary text
text-gray-400dark:text-gray-500Muted text

Brand Colors in Dark Mode

The primary orange stays vibrant but slightly lightened for better contrast:

Light Mode
#FF6B35
Dark Mode
#ff8a66

Card Example

Light Mode
Activity Title
Description text here
Dark Mode
Activity Title
Description text here

Implementation Pattern

Always include both light and dark variants in Tailwind classes:

// Card component
<div className="
bg-white dark:bg-gray-800
text-gray-900 dark:text-gray-100
border border-gray-200 dark:border-gray-700
shadow-sm dark:shadow-gray-900/20
">
<h3 className="text-gray-900 dark:text-white">Title</h3>
<p className="text-gray-600 dark:text-gray-300">Description</p>
</div>

// Button
<button className="
bg-orange-500 hover:bg-orange-600
dark:bg-orange-400 dark:hover:bg-orange-500
text-white
">
Action
</button>

// Input
<input className="
bg-white dark:bg-gray-800
border-gray-300 dark:border-gray-600
text-gray-900 dark:text-gray-100
placeholder-gray-400 dark:placeholder-gray-500
"/>

Status Colors

Status colors remain consistent but may need slight adjustments:

Success (Light)Success (Dark)
Warning (Light)Warning (Dark)
Error (Light)Error (Dark)

New Component Checklist

Every new component must pass this checklist before merge. Copy into your PR description.

Colors

  • All bg-* classes have matching dark:bg-* variants
  • All text-* classes have matching dark:text-* variants
  • All border-* classes have matching dark:border-* variants
  • Text colors maintain 4.5:1 contrast ratio (WCAG AA)
  • Brand orange is legible on dark backgrounds

Interactive States

  • hover: states have matching dark:hover: variants
  • focus: rings/outlines are visible in both modes
  • active: / pressed: states work in both modes
  • Disabled states are distinguishable in both modes

Visual Elements

  • Images/icons are visible in both modes (check SVG fill colors)
  • Shadows use appropriate opacity (shadow-sm vs dark:shadow-gray-900/20)
  • Status colors (success/warning/error) are distinguishable
  • Placeholder text is readable (placeholder-gray-400 dark:placeholder-gray-500)

Verification

  • Visually verified in Storybook with theme toggle
  • Screenshot comparison in both light and dark modes
  • No hardcoded colors (#fff, rgb(...)) — use Tailwind classes only

Common Patterns

// Semantic tokens (preferred)
className="bg-card text-foreground border-border"

// Explicit dark variants (when semantic tokens aren't available)
className="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"

// Status with dark variants
className="bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400"

Test both modes using the theme toggle in Storybook.