diff --git a/CLAUDE.md b/CLAUDE.md index 289f369..54e6275 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,35 @@ # PRIME DIRECTIVES Never use eslint disables for TSC errors. Fix the problem. If you don't know the type, use unknown, never use any. +# CURSOR DIRECTIVES +## Component Creation Priority +1. **ALWAYS check RFDS first**: `import { RFDS } from "@/components/rfds"` +2. **Use Semantic Components**: `RFDS.SemanticButton`, `RFDS.SemanticCard`, `RFDS.SemanticBadge` +3. **Compose from Primitives**: If custom needed, use `RFDS.Button`, `RFDS.Pill`, `RFDS.Rating` +4. **One-off components**: Still use design system primitives as building blocks +5. **NEVER create from scratch**: Always start with design system components + +## Color Usage Rules +- **NEVER use hardcoded colors**: `bg-blue-500`, `text-red-600`, `border-gray-200` +- **ALWAYS use semantic colors**: `bg-primary`, `text-destructive`, `border-border` +- **Check theme-config.ts**: For available semantic color tokens +- **Test both themes**: Light and dark mode compatibility required + +## Default Import Pattern +```typescript +// ✅ CORRECT - Start with design system +import { RFDS } from "@/components/rfds"; + +// Use semantic components first +Click me +Content + +// Compose from primitives if needed +
+ Action +
+``` + # Claude Directives for React Foundation Store ## 🎯 CRITICAL RULES (NEVER BREAK) @@ -83,6 +112,57 @@ import { RFDS } from "@/components/rfds" - **Primitives**: Base building blocks (Button, Typography, etc.) - **Components**: Composed from primitives (ProductCard, etc.) - **Layouts**: Page structure (Header, Footer) +- **Semantic Components**: Themeable components (SemanticButton, SemanticCard, etc.) + +## 🎨 DESIGN SYSTEM & THEMING + +### CRITICAL: Always Use Design System +**NEVER create new components without checking the design system first!** + +#### Design System Hierarchy +1. **Check RFDS first**: `import { RFDS } from "@/components/rfds"` +2. **Use Semantic Components**: For themeable, consistent UI +3. **Compose from Primitives**: If you need something custom +4. **One-off components**: Still use design system primitives + +#### Semantic Theming System +All colors are semantic and themeable. **NEVER use hardcoded colors!** + +```typescript +// ❌ WRONG - Hardcoded colors +
+ +// ✅ CORRECT - Semantic colors +
+``` + +#### Available Semantic Colors +- **Background**: `bg-background`, `bg-card`, `bg-muted` +- **Text**: `text-foreground`, `text-muted-foreground` +- **Interactive**: `bg-primary`, `bg-secondary`, `bg-accent` +- **Status**: `bg-destructive`, `bg-success`, `bg-warning` +- **Borders**: `border-border`, `border-primary`, `border-destructive` + +#### Component Creation Rules +1. **Check RFDS first**: Does `RFDS.SemanticButton` work? +2. **Use semantic components**: `RFDS.SemanticCard`, `RFDS.SemanticBadge` +3. **Compose from primitives**: If custom needed, use `RFDS.Button`, `RFDS.Pill` +4. **Theme-aware**: All components must work in light/dark themes +5. **One-off exception**: Even one-off components should use design system primitives + +#### Migration Script +Use the migration script to convert hardcoded colors: +```bash +node scripts/migrate-to-semantic-colors.js +``` + +#### Theme Configuration +All themes defined in `src/lib/theme-config.ts`: +- Light theme colors +- Dark theme colors +- Semantic color mappings +- Gradient definitions +- Shadow definitions ### Component Patterns - **Functional components**: Use hooks, avoid class components diff --git a/THEMING_GUIDE.md b/THEMING_GUIDE.md new file mode 100644 index 0000000..6b4e806 --- /dev/null +++ b/THEMING_GUIDE.md @@ -0,0 +1,246 @@ +# Theming System Guide + +This guide explains how to use the comprehensive theming system to replace hardcoded colors with semantic, themeable alternatives. + +## 🎨 **Semantic Color System** + +### **Base Colors** +- `bg-background` - Main background color +- `bg-card` - Card/surface background +- `bg-muted` - Muted background for subtle elements +- `text-foreground` - Primary text color +- `text-muted-foreground` - Secondary/muted text color + +### **Interactive Colors** +- `bg-primary` / `text-primary-foreground` - Primary actions +- `bg-secondary` / `text-secondary-foreground` - Secondary actions +- `bg-accent` / `text-accent-foreground` - Accent elements +- `border-border` - Standard borders +- `ring-ring` - Focus rings + +### **Status Colors** +- `bg-destructive` / `text-destructive-foreground` - Errors, delete actions +- `bg-success` / `text-success-foreground` - Success states +- `bg-warning` / `text-warning-foreground` - Warnings + +## 🔄 **Replacing Hardcoded Colors** + +### **Before (Hardcoded)** +```tsx +// ❌ Hardcoded colors - not themeable +
+ +
+``` + +### **After (Semantic)** +```tsx +// ✅ Semantic colors - fully themeable +
+ +
+``` + +## 🛠️ **Common Replacements** + +### **Background Colors** +```tsx +// Replace these hardcoded colors: +bg-white → bg-background +bg-gray-100 → bg-muted +bg-blue-500 → bg-primary +bg-red-500 → bg-destructive +bg-green-500 → bg-success +bg-yellow-500 → bg-warning +``` + +### **Text Colors** +```tsx +// Replace these hardcoded colors: +text-gray-900 → text-foreground +text-gray-600 → text-muted-foreground +text-blue-600 → text-primary +text-red-600 → text-destructive +text-green-600 → text-success +text-yellow-600 → text-warning +``` + +### **Border Colors** +```tsx +// Replace these hardcoded colors: +border-gray-200 → border-border +border-blue-500 → border-primary +border-red-500 → border-destructive +border-green-500 → border-success +border-yellow-500 → border-warning +``` + +### **Shadow Colors** +```tsx +// Replace these hardcoded colors: +shadow-lg → shadow (semantic shadow) +shadow-blue-500/20 → shadowColored (primary colored shadow) +``` + +## 🎯 **Semantic Class Combinations** + +### **Cards** +```tsx +// Use semantic card classes +
+ Card content +
+``` + +### **Buttons** +```tsx +// Use semantic button variants + + + +``` + +### **Status Indicators** +```tsx +// Use semantic status colors +
+ Success message +
+ +
+ Error message +
+``` + +## 🎨 **Gradients** + +### **Semantic Gradients** +```tsx +// Use semantic gradient classes +
+ Primary gradient +
+ +
+ Secondary gradient +
+``` + +## 🔧 **Using Theme Utilities** + +### **Import Theme Utilities** +```tsx +import { themeColors, buttonVariants, semanticClasses } from '@/lib/theme-utils'; +import { cn } from '@/lib/cn'; + +// Use semantic classes +
+ +
+``` + +### **Pre-built Semantic Combinations** +```tsx +import { semanticClasses } from '@/lib/theme-utils'; + +// Use pre-built semantic combinations +
+ +
+``` + +## 🎨 **Creating New Themes** + +### **Add New Theme Colors** +1. Update `src/lib/theme-config.ts` +2. Add new theme colors to the `ThemeColors` interface +3. Define colors for both light and dark themes +4. Update CSS custom properties in `globals.css` + +### **Example: Adding a New Brand Color** +```typescript +// In theme-config.ts +export interface ThemeColors { + // ... existing colors + brand: string; + brandForeground: string; +} + +export const lightTheme: ThemeColors = { + // ... existing colors + brand: '#8b5cf6', + brandForeground: '#ffffff', +}; + +export const darkTheme: ThemeColors = { + // ... existing colors + brand: '#a855f7', + brandForeground: '#ffffff', +}; +``` + +## 🚀 **Best Practices** + +### **Do's** +- ✅ Use semantic color names (`bg-primary`, `text-foreground`) +- ✅ Use theme utilities for common patterns +- ✅ Test both light and dark themes +- ✅ Use consistent color meanings across the app + +### **Don'ts** +- ❌ Use hardcoded Tailwind colors (`bg-blue-500`, `text-red-600`) +- ❌ Mix semantic and hardcoded colors +- ❌ Use colors that don't have semantic meaning +- ❌ Forget to test theme switching + +## 🧪 **Testing Themes** + +### **Manual Testing** +1. Switch between light/dark themes +2. Verify all components adapt correctly +3. Check contrast ratios for accessibility +4. Test with different content lengths + +### **Automated Testing** +```tsx +// Test theme switching in components +import { render } from '@testing-library/react'; +import { ThemeProvider } from '@/components/providers/theme-provider'; + +test('component adapts to dark theme', () => { + render( + + + + ); + // Assert dark theme styles are applied +}); +``` + +## 📝 **Migration Checklist** + +When updating components to use the theming system: + +- [ ] Replace hardcoded background colors with semantic ones +- [ ] Replace hardcoded text colors with semantic ones +- [ ] Replace hardcoded border colors with semantic ones +- [ ] Replace hardcoded shadow colors with semantic ones +- [ ] Test in both light and dark themes +- [ ] Verify accessibility and contrast +- [ ] Update any custom CSS to use CSS custom properties +- [ ] Document any new semantic colors added + +This theming system ensures that all colors are semantic, themeable, and maintainable. By following these patterns, you can easily create new themes or modify existing ones without touching component code. + diff --git a/content/updates/welcome-to-react-foundation.mdx b/content/updates/welcome-to-react-foundation.mdx index 752652c..b58246c 100644 --- a/content/updates/welcome-to-react-foundation.mdx +++ b/content/updates/welcome-to-react-foundation.mdx @@ -8,80 +8,40 @@ draft: false We're thrilled to announce the official launch of the **React Foundation** — a community-driven initiative dedicated to sustaining and advancing the React ecosystem for generations to come. -[Read my full opening message from the Foundation →](/about) - -## Why We're Here - -React has become something bigger than any single company should be responsible for maintaining. Over the past decade — really, the past six years or so — React has become an indispensable part of how the web is built and runs, how Chrome works, and how mobile apps are built. It powers millions of applications across the globe. - -My north star has always been to **change the economic trajectory of people's lives by helping them bring their ideas to life**. React has been transformative in that way, but we still have a long way to go. - -## Four Years in the Making - -This didn't happen overnight. My colleagues at Meta — Matt Carroll, Joe Savona, Eli White, Sophie Alpert, Rick Hanlon and I — spent four years laying the groundwork and preparing React to leave its Meta nest. Meta is laser-focused on AI internally now, but React remains crucial there. In fact, most, if not all, of the tools built at Meta for AI work are built with React. - -The React Foundation isn't about Meta abandoning React. They've contributed the most to spinning up the foundation and have committed for over five years. But it's about involving all the other companies and communities in a way that's much more compatible with keeping React healthy for the long term. - -## What We're Building +## Our Mission The React Foundation exists to ensure the React ecosystem thrives through: - **Funding maintainers** of critical React libraries -- **Investing in community hubs** around the world, especially in underserved areas -- **Fixing React education** — from bootcamps to local meetups -- **Supporting conferences** that align with our values and code of conduct -- **Making React more accessible** to more people worldwide +- **Supporting education** and learning resources +- **Ensuring accessibility** for developers worldwide +- **Transparent governance** and community-driven decision making -## The Bootcamp Problem +## Why Now? -Here's something that keeps me up at night: We have lots of boot camps out there that are doing their best, but they're also sending people out into the world misinformed about how React works. React is very hard to teach, so let's fix that part of React so that it's actually not so hard to teach. +React has grown from a tool built at Meta into a global movement that powers millions of applications. The ecosystem includes 54+ essential libraries maintained by hundreds of contributors across dozens of organizations. -That's why one of our first priorities is to help bootcamps — not just with scholarships, but by improving how React itself is taught. +This growth is incredible — but it also creates sustainability challenges. Many maintainers work on these critical projects in their spare time, without compensation. -## Community Investment - -I want to put gas in the tank of smaller communities to help them flourish. That means: - -- Helping local developer meetups have food, drinks and great speakers -- Bringing in React core team members to teach and align communities -- Supporting amazing community-led conferences (like React Native London, which grew from a meetup!) -- Investing in React hubs around the world, especially in underserved areas +The React Foundation changes that. ## How It Works -Here's something that's been really funny — one of the top requests since people found out about the React Foundation is, "When is the merch store launching?" People around the world want React jackets, React hoodies, React everything. - -Well, it's coming. And here's the thing: **100% of profits from our official merchandise store go directly to ecosystem maintainers**. We track contributions across all 54 supported libraries using transparent, metrics-based distribution. - -The foundation has three funding sources: -1. Corporate sponsorships from our founding members -2. Merchandise store profits (all going to maintainers) -3. React Conf (now able to operate more freely outside of Meta) - -## Governance - -The business governance is being ratified now with our founding corporate partners: - -- **Meta** (committed for 5+ years, supermajority on governance for first 2.5 years) -- **Amazon** -- **Microsoft** -- **Vercel** -- **Expo** -- **Callstack** -- **Software Mansion** +100% of profits from our official merchandise store go directly to ecosystem maintainers. We track contributions across all 54 supported libraries using transparent, metrics-based distribution. -The technical governance will continue much as it has been — with RFCs, public proposals, and stages before reaching canary. We have people on the slate for technical governance roles, and I'm excited about that (names coming soon). +## Founding Members -## My Goals +We're grateful to our founding members who believe in this mission: -Out of the gate, here's what I'm focused on: +- Meta +- Microsoft +- Amazon +- Vercel +- Expo +- Callstack +- Software Mansion -1. **Invest in community hubs** worldwide, especially underserved areas -2. **Fix React education** in bootcamps and learning resources -3. **Support local meetups** and help them grow -4. **Align conferences** with our code of conduct and values -5. **Expand React Conf** with new capabilities now that we're independent -6. **Welcome everyone back** — there's been a lot we've done that's alienated parts of the community. I want to do everything we can to make sure everybody feels as welcome and heard and a part of the React community as they should. +Together, we're building a sustainable future for React. ## Get Involved @@ -89,15 +49,14 @@ Whether you're a contributor, maintainer, or React enthusiast, there are many wa 1. **Shop the store** - Every purchase funds maintainers 2. **Contribute to libraries** - Build the ecosystem -3. **Join a local meetup** - Build community where you are -4. **Spread the word** - Share our mission -5. **Become a member** - Join our governance +3. **Spread the word** - Share our mission +4. **Become a member** - Join our governance -Visit [react.foundation](/) to learn more, or read more about [my vision for the Foundation](/about). +Visit [react.foundation](/) to learn more. --- -Thank you for being part of this journey. React has already changed millions of lives — let's make sure it changes millions more. +Thank you for being part of this journey. **Seth Webster** *Executive Director, React Foundation* diff --git a/debug-theme.html b/debug-theme.html new file mode 100644 index 0000000..38e8b76 --- /dev/null +++ b/debug-theme.html @@ -0,0 +1,18 @@ + + + + + +Open console to see CSS variable values + diff --git a/next.config.ts b/next.config.ts index e479360..7dd46e1 100644 --- a/next.config.ts +++ b/next.config.ts @@ -3,9 +3,7 @@ import createMDX from "@next/mdx"; const nextConfig: NextConfig = { pageExtensions: ["js", "jsx", "md", "mdx", "ts", "tsx"], - experimental: { - reactCompiler: true, // Enable React Compiler v1.0 - }, + reactCompiler: true, // Enable React Compiler v1.0 (moved from experimental) images: { remotePatterns: [ { diff --git a/scripts/migrate-to-semantic-colors.js b/scripts/migrate-to-semantic-colors.js new file mode 100644 index 0000000..e5d9477 --- /dev/null +++ b/scripts/migrate-to-semantic-colors.js @@ -0,0 +1,446 @@ +#!/usr/bin/env node + +/** + * Migration Script: Replace Hardcoded Colors with Semantic Colors + * + * This script systematically replaces hardcoded Tailwind colors with semantic, + * themeable alternatives throughout the codebase. + */ + +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); + +// Color mapping from hardcoded to semantic +const colorMappings = { + // Background colors + 'bg-white': 'bg-background', + 'bg-black': 'bg-foreground', + 'bg-gray-50': 'bg-muted', + 'bg-gray-100': 'bg-muted', + 'bg-gray-200': 'bg-muted', + 'bg-gray-300': 'bg-muted', + 'bg-gray-400': 'bg-muted', + 'bg-gray-500': 'bg-muted', + 'bg-gray-600': 'bg-muted', + 'bg-gray-700': 'bg-muted', + 'bg-gray-800': 'bg-muted', + 'bg-gray-900': 'bg-muted', + 'bg-slate-50': 'bg-muted', + 'bg-slate-100': 'bg-muted', + 'bg-slate-200': 'bg-muted', + 'bg-slate-300': 'bg-muted', + 'bg-slate-400': 'bg-muted', + 'bg-slate-500': 'bg-muted', + 'bg-slate-600': 'bg-muted', + 'bg-slate-700': 'bg-muted', + 'bg-slate-800': 'bg-muted', + 'bg-slate-900': 'bg-muted', + 'bg-slate-950': 'bg-background', + 'bg-zinc-50': 'bg-muted', + 'bg-zinc-100': 'bg-muted', + 'bg-zinc-200': 'bg-muted', + 'bg-zinc-300': 'bg-muted', + 'bg-zinc-400': 'bg-muted', + 'bg-zinc-500': 'bg-muted', + 'bg-zinc-600': 'bg-muted', + 'bg-zinc-700': 'bg-muted', + 'bg-zinc-800': 'bg-muted', + 'bg-zinc-900': 'bg-muted', + 'bg-zinc-950': 'bg-background', + 'bg-neutral-50': 'bg-muted', + 'bg-neutral-100': 'bg-muted', + 'bg-neutral-200': 'bg-muted', + 'bg-neutral-300': 'bg-muted', + 'bg-neutral-400': 'bg-muted', + 'bg-neutral-500': 'bg-muted', + 'bg-neutral-600': 'bg-muted', + 'bg-neutral-700': 'bg-muted', + 'bg-neutral-800': 'bg-muted', + 'bg-neutral-900': 'bg-muted', + 'bg-neutral-950': 'bg-background', + 'bg-stone-50': 'bg-muted', + 'bg-stone-100': 'bg-muted', + 'bg-stone-200': 'bg-muted', + 'bg-stone-300': 'bg-muted', + 'bg-stone-400': 'bg-muted', + 'bg-stone-500': 'bg-muted', + 'bg-stone-600': 'bg-muted', + 'bg-stone-700': 'bg-muted', + 'bg-stone-800': 'bg-muted', + 'bg-stone-900': 'bg-muted', + 'bg-stone-950': 'bg-background', + + // Primary colors + 'bg-blue-50': 'bg-primary/10', + 'bg-blue-100': 'bg-primary/20', + 'bg-blue-200': 'bg-primary/30', + 'bg-blue-300': 'bg-primary/40', + 'bg-blue-400': 'bg-primary/50', + 'bg-blue-500': 'bg-primary', + 'bg-blue-600': 'bg-primary', + 'bg-blue-700': 'bg-primary', + 'bg-blue-800': 'bg-primary', + 'bg-blue-900': 'bg-primary', + 'bg-blue-950': 'bg-primary', + 'bg-sky-50': 'bg-primary/10', + 'bg-sky-100': 'bg-primary/20', + 'bg-sky-200': 'bg-primary/30', + 'bg-sky-300': 'bg-primary/40', + 'bg-sky-400': 'bg-primary/50', + 'bg-sky-500': 'bg-primary', + 'bg-sky-600': 'bg-primary', + 'bg-sky-700': 'bg-primary', + 'bg-sky-800': 'bg-primary', + 'bg-sky-900': 'bg-primary', + 'bg-sky-950': 'bg-primary', + 'bg-indigo-50': 'bg-primary/10', + 'bg-indigo-100': 'bg-primary/20', + 'bg-indigo-200': 'bg-primary/30', + 'bg-indigo-300': 'bg-primary/40', + 'bg-indigo-400': 'bg-primary/50', + 'bg-indigo-500': 'bg-primary', + 'bg-indigo-600': 'bg-primary', + 'bg-indigo-700': 'bg-primary', + 'bg-indigo-800': 'bg-primary', + 'bg-indigo-900': 'bg-primary', + 'bg-indigo-950': 'bg-primary', + 'bg-cyan-50': 'bg-primary/10', + 'bg-cyan-100': 'bg-primary/20', + 'bg-cyan-200': 'bg-primary/30', + 'bg-cyan-300': 'bg-primary/40', + 'bg-cyan-400': 'bg-primary/50', + 'bg-cyan-500': 'bg-primary', + 'bg-cyan-600': 'bg-primary', + 'bg-cyan-700': 'bg-primary', + 'bg-cyan-800': 'bg-primary', + 'bg-cyan-900': 'bg-primary', + 'bg-cyan-950': 'bg-primary', + + // Success colors + 'bg-green-50': 'bg-success/10', + 'bg-green-100': 'bg-success/20', + 'bg-green-200': 'bg-success/30', + 'bg-green-300': 'bg-success/40', + 'bg-green-400': 'bg-success/50', + 'bg-green-500': 'bg-success', + 'bg-green-600': 'bg-success', + 'bg-green-700': 'bg-success', + 'bg-green-800': 'bg-success', + 'bg-green-900': 'bg-success', + 'bg-green-950': 'bg-success', + 'bg-emerald-50': 'bg-success/10', + 'bg-emerald-100': 'bg-success/20', + 'bg-emerald-200': 'bg-success/30', + 'bg-emerald-300': 'bg-success/40', + 'bg-emerald-400': 'bg-success/50', + 'bg-emerald-500': 'bg-success', + 'bg-emerald-600': 'bg-success', + 'bg-emerald-700': 'bg-success', + 'bg-emerald-800': 'bg-success', + 'bg-emerald-900': 'bg-success', + 'bg-emerald-950': 'bg-success', + 'bg-lime-50': 'bg-success/10', + 'bg-lime-100': 'bg-success/20', + 'bg-lime-200': 'bg-success/30', + 'bg-lime-300': 'bg-success/40', + 'bg-lime-400': 'bg-success/50', + 'bg-lime-500': 'bg-success', + 'bg-lime-600': 'bg-success', + 'bg-lime-700': 'bg-success', + 'bg-lime-800': 'bg-success', + 'bg-lime-900': 'bg-success', + 'bg-lime-950': 'bg-success', + 'bg-teal-50': 'bg-success/10', + 'bg-teal-100': 'bg-success/20', + 'bg-teal-200': 'bg-success/30', + 'bg-teal-300': 'bg-success/40', + 'bg-teal-400': 'bg-success/50', + 'bg-teal-500': 'bg-success', + 'bg-teal-600': 'bg-success', + 'bg-teal-700': 'bg-success', + 'bg-teal-800': 'bg-success', + 'bg-teal-900': 'bg-success', + 'bg-teal-950': 'bg-success', + + // Destructive colors + 'bg-red-50': 'bg-destructive/10', + 'bg-red-100': 'bg-destructive/20', + 'bg-red-200': 'bg-destructive/30', + 'bg-red-300': 'bg-destructive/40', + 'bg-red-400': 'bg-destructive/50', + 'bg-red-500': 'bg-destructive', + 'bg-red-600': 'bg-destructive', + 'bg-red-700': 'bg-destructive', + 'bg-red-800': 'bg-destructive', + 'bg-red-900': 'bg-destructive', + 'bg-red-950': 'bg-destructive', + 'bg-rose-50': 'bg-destructive/10', + 'bg-rose-100': 'bg-destructive/20', + 'bg-rose-200': 'bg-destructive/30', + 'bg-rose-300': 'bg-destructive/40', + 'bg-rose-400': 'bg-destructive/50', + 'bg-rose-500': 'bg-destructive', + 'bg-rose-600': 'bg-destructive', + 'bg-rose-700': 'bg-destructive', + 'bg-rose-800': 'bg-destructive', + 'bg-rose-900': 'bg-destructive', + 'bg-rose-950': 'bg-destructive', + + // Warning colors + 'bg-yellow-50': 'bg-warning/10', + 'bg-yellow-100': 'bg-warning/20', + 'bg-yellow-200': 'bg-warning/30', + 'bg-yellow-300': 'bg-warning/40', + 'bg-yellow-400': 'bg-warning/50', + 'bg-yellow-500': 'bg-warning', + 'bg-yellow-600': 'bg-warning', + 'bg-yellow-700': 'bg-warning', + 'bg-yellow-800': 'bg-warning', + 'bg-yellow-900': 'bg-warning', + 'bg-yellow-950': 'bg-warning', + 'bg-amber-50': 'bg-warning/10', + 'bg-amber-100': 'bg-warning/20', + 'bg-amber-200': 'bg-warning/30', + 'bg-amber-300': 'bg-warning/40', + 'bg-amber-400': 'bg-warning/50', + 'bg-amber-500': 'bg-warning', + 'bg-amber-600': 'bg-warning', + 'bg-amber-700': 'bg-warning', + 'bg-amber-800': 'bg-warning', + 'bg-amber-900': 'bg-warning', + 'bg-amber-950': 'bg-warning', + 'bg-orange-50': 'bg-warning/10', + 'bg-orange-100': 'bg-warning/20', + 'bg-orange-200': 'bg-warning/30', + 'bg-orange-300': 'bg-warning/40', + 'bg-orange-400': 'bg-warning/50', + 'bg-orange-500': 'bg-warning', + 'bg-orange-600': 'bg-warning', + 'bg-orange-700': 'bg-warning', + 'bg-orange-800': 'bg-warning', + 'bg-orange-900': 'bg-warning', + 'bg-orange-950': 'bg-warning', + + // Accent colors + 'bg-purple-50': 'bg-accent/10', + 'bg-purple-100': 'bg-accent/20', + 'bg-purple-200': 'bg-accent/30', + 'bg-purple-300': 'bg-accent/40', + 'bg-purple-400': 'bg-accent/50', + 'bg-purple-500': 'bg-accent', + 'bg-purple-600': 'bg-accent', + 'bg-purple-700': 'bg-accent', + 'bg-purple-800': 'bg-accent', + 'bg-purple-900': 'bg-accent', + 'bg-purple-950': 'bg-accent', + 'bg-violet-50': 'bg-accent/10', + 'bg-violet-100': 'bg-accent/20', + 'bg-violet-200': 'bg-accent/30', + 'bg-violet-300': 'bg-accent/40', + 'bg-violet-400': 'bg-accent/50', + 'bg-violet-500': 'bg-accent', + 'bg-violet-600': 'bg-accent', + 'bg-violet-700': 'bg-accent', + 'bg-violet-800': 'bg-accent', + 'bg-violet-900': 'bg-accent', + 'bg-violet-950': 'bg-accent', + 'bg-fuchsia-50': 'bg-accent/10', + 'bg-fuchsia-100': 'bg-accent/20', + 'bg-fuchsia-200': 'bg-accent/30', + 'bg-fuchsia-300': 'bg-accent/40', + 'bg-fuchsia-400': 'bg-accent/50', + 'bg-fuchsia-500': 'bg-accent', + 'bg-fuchsia-600': 'bg-accent', + 'bg-fuchsia-700': 'bg-accent', + 'bg-fuchsia-800': 'bg-accent', + 'bg-fuchsia-900': 'bg-accent', + 'bg-fuchsia-950': 'bg-accent', + 'bg-pink-50': 'bg-accent/10', + 'bg-pink-100': 'bg-accent/20', + 'bg-pink-200': 'bg-accent/30', + 'bg-pink-300': 'bg-accent/40', + 'bg-pink-400': 'bg-accent/50', + 'bg-pink-500': 'bg-accent', + 'bg-pink-600': 'bg-accent', + 'bg-pink-700': 'bg-accent', + 'bg-pink-800': 'bg-accent', + 'bg-pink-900': 'bg-accent', + 'bg-pink-950': 'bg-accent', +}; + +// Text color mappings (similar pattern) +const textColorMappings = { + 'text-white': 'text-foreground', + 'text-black': 'text-foreground', + 'text-gray-50': 'text-muted-foreground', + 'text-gray-100': 'text-muted-foreground', + 'text-gray-200': 'text-muted-foreground', + 'text-gray-300': 'text-muted-foreground', + 'text-gray-400': 'text-muted-foreground', + 'text-gray-500': 'text-muted-foreground', + 'text-gray-600': 'text-muted-foreground', + 'text-gray-700': 'text-foreground', + 'text-gray-800': 'text-foreground', + 'text-gray-900': 'text-foreground', + 'text-slate-50': 'text-muted-foreground', + 'text-slate-100': 'text-muted-foreground', + 'text-slate-200': 'text-muted-foreground', + 'text-slate-300': 'text-muted-foreground', + 'text-slate-400': 'text-muted-foreground', + 'text-slate-500': 'text-muted-foreground', + 'text-slate-600': 'text-muted-foreground', + 'text-slate-700': 'text-foreground', + 'text-slate-800': 'text-foreground', + 'text-slate-900': 'text-foreground', + 'text-slate-950': 'text-foreground', + 'text-blue-500': 'text-primary', + 'text-blue-600': 'text-primary', + 'text-blue-700': 'text-primary', + 'text-sky-500': 'text-primary', + 'text-sky-600': 'text-primary', + 'text-sky-700': 'text-primary', + 'text-indigo-500': 'text-primary', + 'text-indigo-600': 'text-primary', + 'text-indigo-700': 'text-primary', + 'text-cyan-500': 'text-primary', + 'text-cyan-600': 'text-primary', + 'text-cyan-700': 'text-primary', + 'text-green-500': 'text-success', + 'text-green-600': 'text-success', + 'text-green-700': 'text-success', + 'text-emerald-500': 'text-success', + 'text-emerald-600': 'text-success', + 'text-emerald-700': 'text-success', + 'text-red-500': 'text-destructive', + 'text-red-600': 'text-destructive', + 'text-red-700': 'text-destructive', + 'text-rose-500': 'text-destructive', + 'text-rose-600': 'text-destructive', + 'text-rose-700': 'text-destructive', + 'text-yellow-500': 'text-warning', + 'text-yellow-600': 'text-warning', + 'text-yellow-700': 'text-warning', + 'text-amber-500': 'text-warning', + 'text-amber-600': 'text-warning', + 'text-amber-700': 'text-warning', + 'text-purple-500': 'text-accent', + 'text-purple-600': 'text-accent', + 'text-purple-700': 'text-accent', + 'text-violet-500': 'text-accent', + 'text-violet-600': 'text-accent', + 'text-violet-700': 'text-accent', +}; + +// Border color mappings +const borderColorMappings = { + 'border-white': 'border-border', + 'border-black': 'border-border', + 'border-gray-200': 'border-border', + 'border-gray-300': 'border-border', + 'border-slate-200': 'border-border', + 'border-slate-300': 'border-border', + 'border-blue-500': 'border-primary', + 'border-sky-500': 'border-primary', + 'border-indigo-500': 'border-primary', + 'border-cyan-500': 'border-primary', + 'border-green-500': 'border-success', + 'border-emerald-500': 'border-success', + 'border-red-500': 'border-destructive', + 'border-rose-500': 'border-destructive', + 'border-yellow-500': 'border-warning', + 'border-amber-500': 'border-warning', + 'border-purple-500': 'border-accent', + 'border-violet-500': 'border-accent', +}; + +// Combine all mappings +const allMappings = { + ...colorMappings, + ...textColorMappings, + ...borderColorMappings, +}; + +function migrateFile(filePath) { + try { + let content = fs.readFileSync(filePath, 'utf8'); + let hasChanges = false; + + // Apply all color mappings + for (const [hardcoded, semantic] of Object.entries(allMappings)) { + const regex = new RegExp(`\\b${hardcoded}\\b`, 'g'); + if (content.includes(hardcoded)) { + content = content.replace(regex, semantic); + hasChanges = true; + } + } + + if (hasChanges) { + fs.writeFileSync(filePath, content, 'utf8'); + console.log(`✅ Migrated: ${filePath}`); + return true; + } + + return false; + } catch (error) { + console.error(`❌ Error migrating ${filePath}:`, error.message); + return false; + } +} + +function findTsxFiles(dir) { + const files = []; + + function traverse(currentDir) { + const items = fs.readdirSync(currentDir); + + for (const item of items) { + const fullPath = path.join(currentDir, item); + const stat = fs.statSync(fullPath); + + if (stat.isDirectory() && !item.startsWith('.') && item !== 'node_modules') { + traverse(fullPath); + } else if (item.endsWith('.tsx') || item.endsWith('.ts')) { + files.push(fullPath); + } + } + } + + traverse(dir); + return files; +} + +function main() { + console.log('🚀 Starting semantic color migration...\n'); + + const srcDir = path.join(__dirname, '..', 'src'); + const files = findTsxFiles(srcDir); + + let migratedCount = 0; + let totalFiles = files.length; + + console.log(`Found ${totalFiles} files to process...\n`); + + for (const file of files) { + if (migrateFile(file)) { + migratedCount++; + } + } + + console.log(`\n✨ Migration complete!`); + console.log(`📊 Migrated ${migratedCount} out of ${totalFiles} files`); + + if (migratedCount > 0) { + console.log('\n🔍 Next steps:'); + console.log('1. Review the changes'); + console.log('2. Test theme switching'); + console.log('3. Run linting: npm run lint'); + console.log('4. Run tests: npm test'); + } +} + +if (require.main === module) { + main(); +} + +module.exports = { migrateFile, allMappings }; diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index e1d3aff..734df73 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -15,7 +15,7 @@ export const metadata: Metadata = { export default function AboutPage() { return ( -
+
@@ -26,10 +26,10 @@ export default function AboutPage() {
Our Story · Our Mission · Our Values
-

+

About React Foundation

-

+

We're building a sustainable future for the React ecosystem through community funding, transparent governance, and unwavering support for the maintainers who make it all possible. @@ -42,11 +42,11 @@ export default function AboutPage() { {/* Mission */} -

-

+
+

Our Mission

-

+

The React Foundation exists to ensure the React ecosystem thrives for generations to come. We provide direct financial support to maintainers, fund educational initiatives, and ensure accessibility for developers @@ -54,34 +54,34 @@ export default function AboutPage() {

-
-
+
+
-

Sustainable Funding

-

+

Sustainable Funding

+

Creating reliable revenue streams that support open source maintainers

-
-
+
+
-

Full Transparency

-

+

Full Transparency

+

Quarterly reports showing exactly how funds are distributed

-
-
+
+
-

Community First

-

+

Community First

+

Decisions driven by community needs and maintainer feedback

@@ -92,58 +92,58 @@ export default function AboutPage() { {/* How It Works */} -
-

+
+

How It Works

-
+
- 1 + 1
-

+

Shop the Store

-

+

Browse our collection of premium React-themed merchandise. Every purchase directly supports the ecosystem.

-
+
- 2 + 2
-

+

Revenue Distribution

-

+

100% of profits are distributed to maintainers of 54+ React ecosystem libraries based on contribution metrics.

-
-
- 3 +
+
+ 3
-

+

Contributor Recognition

-

+

Contributors unlock exclusive merchandise tiers (Contributor, Sustainer, Core) based on their ecosystem contributions.

-
+
- 4 + 4
-

+

Transparent Reporting

-

+

Quarterly impact reports detail exactly how funds support maintainers, education, and accessibility initiatives.

@@ -163,37 +163,37 @@ export default function AboutPage() { {/* Governance */} -
-

+
+

Transparent Governance

-

+

The React Foundation operates with complete transparency. All funding decisions, impact reports, and financial details are published quarterly for community review and feedback.

-
-

Open Financials

-

+

+

Open Financials

+

Every dollar tracked and reported publicly

-
-

Community Input

-

+

+

Community Input

+

Major decisions informed by maintainer feedback

-
-

Quarterly Reports

-

+

+

Quarterly Reports

+

Detailed impact metrics published every quarter

-
-

Open Source Values

-

+

+

Open Source Values

+

Built on the same principles as the ecosystem we support

@@ -208,11 +208,11 @@ export default function AboutPage() { {/* CTA */} -
-

+
+

Ready to Make an Impact?

-

+

Start supporting the React ecosystem today. Every contribution helps build a sustainable future for open source.

diff --git a/src/app/admin/admin-sidebar.tsx b/src/app/admin/admin-sidebar.tsx index 0304f9d..9ae409d 100644 --- a/src/app/admin/admin-sidebar.tsx +++ b/src/app/admin/admin-sidebar.tsx @@ -17,10 +17,10 @@ export function AdminSidebar() { ]; return ( -