This document explains the theme-aware text color system that has been implemented in the DevPath-Web application. Text colors now automatically adjust based on the current theme (light/dark mode) without requiring component-level theme detection.
The following CSS variables have been added to support theme-aware text colors:
--text-primary: #0f172a; /* Dark slate for main text */
--text-secondary: #64748b; /* Medium slate for secondary text */
--text-muted: #94a3b8; /* Light slate for muted text */
--text-light: #f1f5f9; /* Light color for text on dark backgrounds */
--text-dark: #0f172a; /* Dark color for text on light backgrounds */--text-primary: #ffffff; /* White for main text */
--text-secondary: #94a3b8; /* Slate for secondary text */
--text-muted: #64748b; /* Darker slate for muted text */
--text-light: #e2e8f0; /* Light color for text */
--text-dark: #ffffff; /* White for dark theme */New utility classes for easy theme-aware styling:
.text-primary-theme /* Main text color with transition */
.text-secondary-theme /* Secondary text color with transition */
.text-muted-theme /* Muted text color with transition */
.text-light-theme /* Light text color with transition */
.text-dark-theme /* Dark text color with transition */
/* Theme-aware alternatives for specific grays */
.theme-aware-gray /* Gray text that becomes lighter in dark mode */
.theme-aware-black /* Black text that becomes white in dark mode */
.theme-aware-light-gray /* Light gray text */
.theme-aware-subtle-gray /* Subtle gray text */
.theme-aware-dark-gray /* Dark gray text */The following components have been updated to use theme-aware colors:
- Hero.tsx - Already using
var(--text-secondary) - Sponsors.module.css - Updated text color
- Resources.module.css - Updated hover state colors
- CodingNews.module.css - Updated multiple text colors
- RepoModal.module.css - Updated all text colors
- InteractiveSteps.module.css - Updated text colors
- page.module.css - Uses light/dark mode detection
Use CSS variables for text colors:
.myComponent {
color: var(--text-primary); /* Main text */
}
.myComponent p {
color: var(--text-secondary); /* Secondary text */
}
.myComponent .helper {
color: var(--text-muted); /* Muted/disabled text */
}Use Tailwind classes (already configured):
{/* Using Tailwind's default theme colors */}
<h1 className="text-foreground">Main heading</h1>
<p className="text-muted-foreground">Helper text</p>
{/* Or use utility classes from globals.css */}
<div className="text-primary-theme">
This text adjusts automatically
</div>Import and use the theme helper:
import { useThemeColors } from '@/lib/theme';
function MyComponent() {
const { textPrimary, textSecondary } = useThemeColors();
return (
<>
<p style={{ color: textPrimary }}>Main text</p>
<p style={{ color: textSecondary }}>Secondary text</p>
</>
);
}-
Use CSS variables for static colors:
color: var(--text-primary);
-
Use Tailwind classes when possible:
className="text-foreground" className="text-muted-foreground"
-
Add smooth transitions:
color: var(--text-primary); transition: color var(--transition-fast);
-
Use appropriate text colors for hierarchy:
- Main content:
--text-primary - Secondary info:
--text-secondary - Disabled/hint text:
--text-muted
- Main content:
-
Avoid hardcoded color values:
/* ❌ BAD */ color: #000000; color: #ffffff; color: #666666;
-
Don't mix theme approaches:
/* ❌ BAD */ .myClass { color: white; /* Will be invisible in light mode */ }
-
Don't forget transitions:
/* ❌ Jarring color change */ color: var(--text-primary); /* without transition */ /* ✅ Smooth transition */ color: var(--text-primary); transition: color var(--transition-fast);
| Variable | Light Mode | Dark Mode | Use Case |
|---|---|---|---|
--text-primary |
#0f172a | #ffffff | Main headings and body text |
--text-secondary |
#64748b | #94a3b8 | Secondary information, captions |
--text-muted |
#94a3b8 | #64748b | Disabled, placeholder, helper text |
--text-light |
#f1f5f9 | #e2e8f0 | Text on dark backgrounds |
--text-dark |
#0f172a | #ffffff | Text on light backgrounds |
--accent-cyan: #00d4ff--accent-purple: #9d4edd--accent-pink: #ff006e--accent-green: #00ff88--accent-orange: #ff6b35
If you're updating existing components:
-
Find hardcoded text colors:
grep -r "color: #" src/components --include="*.module.css"
-
Replace with variables:
/* Before */ color: #475569; /* After */ color: var(--text-secondary);
-
Add transitions:
color: var(--text-secondary); transition: color var(--transition-fast);
To verify theme-aware colors are working:
- Open the app in light mode (default)
- Observe text colors match the light mode palette
- Switch to dark mode
- Observe text colors smoothly transition to dark mode palette
- Check that all text remains readable in both modes
Problem: Text color is hardcoded as white or black
Solution: Replace with var(--text-primary) or appropriate variable
Problem: Missing transition property
Solution: Add transition: color var(--transition-fast);
Problem: Inline styles or wrong variable names Solution: Use CSS variables instead of inline styles, verify variable names
src/app/globals.css- Added new CSS variables and utility classessrc/components/home/Sponsors.module.css- Updated to use theme variablessrc/components/home/Resources.module.css- Updated hover colorssrc/components/home/CodingNews.module.css- Updated text colorssrc/components/source-code/RepoModal.module.css- Updated all text colorssrc/components/source-code/InteractiveSteps.module.css- Updated text colorssrc/lib/theme.ts- Created theme utility file
- Create React hook for theme detection:
useTheme() - Add theme transition animations
- Create Storybook stories for theme testing
- Add accessibility contrast ratio validation
- Create theme designer tool for custom color schemes