Move docs/ package mirror into document-navigator plugin

Relocate the ~6k-file docs tree from the repo root into
plugins/document-navigator/docs/ so the plugin is self-contained and
portable. docs/superpowers/ (specs and plans) stays at the repo root.

Moved via cp+rm rather than git mv because directory rename() fails with
EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the
identical-content files at commit time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-30 01:10:00 +01:00
parent fe3fedf42e
commit 9bf56a806b
6022 changed files with 12437 additions and 0 deletions

View File

@@ -0,0 +1,723 @@
---
name: theme-factory
description: Generate and apply Tailwind CSS + shadcn/ui themes for Suaveplan React applications using HSL CSS variables, dark mode variants, and component-level theming
---
# Theme Factory for Suaveplan
Generate complete Tailwind CSS theme configurations compatible with `@suaveplan/react-ui` (shadcn/ui). Each theme defines HSL CSS variables for `:root` (light) and `.dark` (dark mode), extending the Tailwind config to provide consistent styling across all Suaveplan React components.
## Architecture
| Layer | Technology |
|-------|-----------|
| Color Format | HSL (required for shadcn/ui compatibility) |
| Variable Scope | CSS custom properties on `:root` and `.dark` |
| Dark Mode | Tailwind `dark:` variant via `class` strategy |
| Component Library | `@suaveplan/react-ui` (shadcn/ui-based) |
| Class Merging | `cn()` from `@suaveplan/react-ui` |
| Build | Tailwind CSS PostCSS pipeline via Vite |
## Theme Variables
Every Suaveplan theme must define these CSS variables in HSL format (hue saturation lightness without commas, no `hsl()` wrapper):
### Required Variables
```css
:root {
/* Page */
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
/* Card surfaces */
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
/* Popover surfaces */
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
/* Primary actions */
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
/* Secondary actions */
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
/* Subdued elements */
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
/* Highlights and hover states */
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
/* Errors and destructive actions */
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
/* Borders and separators */
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
/* Focus rings */
--ring: 222.2 84% 4.9%;
/* Border radius scale */
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
```
### Optional Extended Variables
For advanced themes, add sidebar and chart variables:
```css
:root {
/* Sidebar (used by @suaveplan/react-ui sidebar component) */
--sidebar-background: 0 0% 98%;
--sidebar-foreground: 240 5.3% 26.1%;
--sidebar-primary: 240 5.9% 10%;
--sidebar-primary-foreground: 0 0% 98%;
--sidebar-accent: 240 4.8% 95.9%;
--sidebar-accent-foreground: 240 5.9% 10%;
--sidebar-border: 220 13% 91%;
--sidebar-ring: 217.2 91.2% 59.8%;
/* Charts (used by @suaveplan/react-charts) */
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
}
```
## Tailwind Configuration Extension
Extend the Tailwind config to consume CSS variables:
```typescript
// tailwind.config.ts
import type { Config } from 'tailwindcss';
const config: Config = {
darkMode: 'class',
content: ['./src/**/*.{ts,tsx}'],
theme: {
extend: {
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))',
},
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
},
},
};
export default config;
```
## 10 Built-In Themes
### 1. Default (Zinc)
The standard Suaveplan theme. Neutral zinc scale with sharp contrasts.
```css
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
}
```
### 2. Slate
Cool blue-gray tone. Professional, corporate.
```css
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
```
### 3. Ocean Blue
Vibrant blue primary. Energetic, tech-forward.
```css
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--primary: 217.2 91.2% 59.8%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 217.2 91.2% 59.8%;
}
```
### 4. Emerald
Green primary. Growth, health, sustainability.
```css
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 160.1 84.1% 39.4%;
--primary-foreground: 0 0% 98%;
--secondary: 140 30% 95%;
--secondary-foreground: 160.1 84.1% 25%;
--muted: 140 20% 96%;
--muted-foreground: 150 10% 45%;
--accent: 140 30% 95%;
--accent-foreground: 160.1 84.1% 25%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 140 20% 90%;
--input: 140 20% 90%;
--ring: 160.1 84.1% 39.4%;
--radius: 0.5rem;
}
.dark {
--background: 150 30% 4%;
--foreground: 140 20% 98%;
--primary: 160.1 84.1% 39.4%;
--primary-foreground: 0 0% 98%;
--secondary: 150 20% 15%;
--secondary-foreground: 140 20% 98%;
--muted: 150 20% 15%;
--muted-foreground: 150 15% 60%;
--accent: 150 20% 15%;
--accent-foreground: 140 20% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 150 20% 15%;
--input: 150 20% 15%;
--ring: 160.1 84.1% 39.4%;
}
```
### 5. Rose
Pink-red primary. Bold, creative, expressive.
```css
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 346.8 77.2% 49.8%;
--primary-foreground: 355.7 100% 97.3%;
--secondary: 340 30% 96%;
--secondary-foreground: 346.8 77.2% 35%;
--muted: 340 20% 96%;
--muted-foreground: 340 10% 45%;
--accent: 340 30% 96%;
--accent-foreground: 346.8 77.2% 35%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 340 20% 91%;
--input: 340 20% 91%;
--ring: 346.8 77.2% 49.8%;
--radius: 0.5rem;
}
.dark {
--background: 340 30% 4%;
--foreground: 340 10% 98%;
--primary: 346.8 77.2% 49.8%;
--primary-foreground: 355.7 100% 97.3%;
--secondary: 340 20% 15%;
--secondary-foreground: 340 10% 98%;
--muted: 340 20% 15%;
--muted-foreground: 340 15% 60%;
--accent: 340 20% 15%;
--accent-foreground: 340 10% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 340 20% 15%;
--input: 340 20% 15%;
--ring: 346.8 77.2% 49.8%;
}
```
### 6. Amber
Warm amber/orange primary. Friendly, approachable, energetic.
```css
:root {
--background: 0 0% 100%;
--foreground: 20 14.3% 4.1%;
--primary: 24.6 95% 53.1%;
--primary-foreground: 60 9.1% 97.8%;
--secondary: 30 30% 96%;
--secondary-foreground: 24.6 95% 30%;
--muted: 30 20% 96%;
--muted-foreground: 25 10% 45%;
--accent: 30 30% 96%;
--accent-foreground: 24.6 95% 30%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 30 20% 90%;
--input: 30 20% 90%;
--ring: 24.6 95% 53.1%;
--radius: 0.5rem;
}
.dark {
--background: 20 14.3% 4.1%;
--foreground: 60 9.1% 97.8%;
--primary: 20.5 90.2% 48.2%;
--primary-foreground: 60 9.1% 97.8%;
--secondary: 20 20% 15%;
--secondary-foreground: 60 9.1% 97.8%;
--muted: 20 20% 15%;
--muted-foreground: 25 15% 60%;
--accent: 20 20% 15%;
--accent-foreground: 60 9.1% 97.8%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 20 20% 15%;
--input: 20 20% 15%;
--ring: 20.5 90.2% 48.2%;
}
```
### 7. Violet
Purple primary. Premium, creative, distinctive.
```css
:root {
--background: 0 0% 100%;
--foreground: 224 71.4% 4.1%;
--primary: 262.1 83.3% 57.8%;
--primary-foreground: 210 20% 98%;
--secondary: 260 30% 96%;
--secondary-foreground: 262.1 83.3% 35%;
--muted: 260 20% 96%;
--muted-foreground: 260 10% 45%;
--accent: 260 30% 96%;
--accent-foreground: 262.1 83.3% 35%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 260 20% 91%;
--input: 260 20% 91%;
--ring: 262.1 83.3% 57.8%;
--radius: 0.5rem;
}
.dark {
--background: 260 30% 4%;
--foreground: 260 10% 98%;
--primary: 263.4 70% 50.4%;
--primary-foreground: 210 20% 98%;
--secondary: 260 20% 15%;
--secondary-foreground: 260 10% 98%;
--muted: 260 20% 15%;
--muted-foreground: 260 15% 60%;
--accent: 260 20% 15%;
--accent-foreground: 260 10% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 260 20% 15%;
--input: 260 20% 15%;
--ring: 263.4 70% 50.4%;
}
```
### 8. Neutral
Pure grayscale. Minimal, content-focused, photography-friendly.
```css
:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--primary-foreground: 0 0% 98%;
--secondary: 0 0% 96.1%;
--secondary-foreground: 0 0% 9%;
--muted: 0 0% 96.1%;
--muted-foreground: 0 0% 45.1%;
--accent: 0 0% 96.1%;
--accent-foreground: 0 0% 9%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 89.8%;
--input: 0 0% 89.8%;
--ring: 0 0% 3.9%;
--radius: 0.5rem;
}
.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 0 0% 9%;
--secondary: 0 0% 14.9%;
--secondary-foreground: 0 0% 98%;
--muted: 0 0% 14.9%;
--muted-foreground: 0 0% 63.9%;
--accent: 0 0% 14.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
}
```
### 9. Teal
Blue-green primary. Calming, trustworthy, health/wellness.
```css
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 175 84% 32%;
--primary-foreground: 0 0% 98%;
--secondary: 170 30% 95%;
--secondary-foreground: 175 84% 22%;
--muted: 170 20% 96%;
--muted-foreground: 170 10% 45%;
--accent: 170 30% 95%;
--accent-foreground: 175 84% 22%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 170 20% 90%;
--input: 170 20% 90%;
--ring: 175 84% 32%;
--radius: 0.5rem;
}
.dark {
--background: 175 30% 4%;
--foreground: 170 20% 98%;
--primary: 175 84% 32%;
--primary-foreground: 0 0% 98%;
--secondary: 175 20% 15%;
--secondary-foreground: 170 20% 98%;
--muted: 175 20% 15%;
--muted-foreground: 170 15% 60%;
--accent: 175 20% 15%;
--accent-foreground: 170 20% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 175 20% 15%;
--input: 175 20% 15%;
--ring: 175 84% 32%;
}
```
### 10. Crimson
Deep red primary. Bold, authoritative, editorial.
```css
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 0 72.2% 50.6%;
--primary-foreground: 0 85.7% 97.3%;
--secondary: 0 20% 96%;
--secondary-foreground: 0 72.2% 35%;
--muted: 0 15% 96%;
--muted-foreground: 0 8% 45%;
--accent: 0 20% 96%;
--accent-foreground: 0 72.2% 35%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 0 15% 91%;
--input: 0 15% 91%;
--ring: 0 72.2% 50.6%;
--radius: 0.5rem;
}
.dark {
--background: 0 20% 4%;
--foreground: 0 10% 98%;
--primary: 0 72.2% 50.6%;
--primary-foreground: 0 85.7% 97.3%;
--secondary: 0 15% 15%;
--secondary-foreground: 0 10% 98%;
--muted: 0 15% 15%;
--muted-foreground: 0 10% 60%;
--accent: 0 15% 15%;
--accent-foreground: 0 10% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 0 15% 15%;
--input: 0 15% 15%;
--ring: 0 72.2% 50.6%;
}
```
## Applying a Theme
### Method 1: Global CSS (Single Theme)
Place variables in the app's global CSS file:
```css
/* apps/web/src/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
/* ... rest of light theme variables */
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
/* ... rest of dark theme variables */
}
}
```
### Method 2: Theme Switcher (Multiple Themes)
Use data attributes to switch between themes at runtime:
```css
/* themes.css */
[data-theme="default"] { /* ... zinc variables ... */ }
[data-theme="ocean"] { /* ... ocean blue variables ... */ }
[data-theme="emerald"] { /* ... emerald variables ... */ }
/* ... */
[data-theme="default"].dark { /* ... zinc dark variables ... */ }
[data-theme="ocean"].dark { /* ... ocean blue dark variables ... */ }
```
```typescript
// Theme switcher component
import * as React from 'react';
const themes = [
'default', 'slate', 'ocean', 'emerald', 'rose',
'amber', 'violet', 'neutral', 'teal', 'crimson',
] as const;
type Theme = (typeof themes)[number];
export function useTheme() {
const [theme, setTheme] = React.useState<Theme>('default');
const [dark, setDark] = React.useState(false);
React.useEffect(() => {
document.documentElement.setAttribute('data-theme', theme);
document.documentElement.classList.toggle('dark', dark);
}, [theme, dark]);
return { theme, setTheme, dark, setDark, themes };
}
```
### Method 3: Component-Level Theming
Override variables on a specific container for scoped theming:
```typescript
import { cn } from '@suaveplan/react-ui';
export function BrandedSection({ children, className }: { children: React.ReactNode; className?: string }) {
return (
<section
className={cn('rounded-lg p-6', className)}
style={{
'--primary': '221.2 83.2% 53.3%',
'--primary-foreground': '210 40% 98%',
} as React.CSSProperties}
>
{children}
</section>
);
}
```
## Creating a Custom Theme
### Step-by-Step
1. **Choose a primary hue** (0-360 on the HSL wheel)
2. **Set primary saturation** (60-90% for vibrant, 30-50% for muted)
3. **Derive secondary** from primary hue with lower saturation and higher lightness
4. **Derive muted** from primary hue with very low saturation (15-25%) and high lightness (95-97%)
5. **Set accent** equal to secondary (or slightly different hue for contrast)
6. **Keep destructive** at red (hue 0) -- users expect red for errors
7. **Derive border** from muted with slightly lower lightness
8. **Set ring** equal to primary (focus rings should match primary actions)
9. **Dark mode**: Invert lightness values -- backgrounds become dark (3-5%), foregrounds become light (95-98%)
### Contrast Requirements
All theme color pairs must meet WCAG 2.1 AA contrast ratios:
- **Normal text**: minimum 4.5:1 contrast ratio
- **Large text** (18px+ or 14px+ bold): minimum 3:1 contrast ratio
- **UI components**: minimum 3:1 against adjacent colors
Verify with: `foreground` against `background`, `primary-foreground` against `primary`, etc.
## Constraints
- **HSL format only** -- no hex, rgb, or oklch in CSS variables
- **No `hsl()` wrapper** in variable values -- Tailwind adds it via `hsl(var(--name))`
- **All 14 required variables** must be defined in both `:root` and `.dark`
- **WCAG AA contrast** on all foreground/background pairs
- **`dark:` variant** must be supported -- no light-only themes
- **`--radius`** must be included (default `0.5rem`)
- **No Tailwind color utilities** (`bg-blue-500`) for themed elements -- always use semantic tokens (`bg-primary`)
- Components must use `cn()` from `@suaveplan/react-ui` for class merging