# WorkRoot Component Library

A reference for all reusable UI components. Every component listed here fully supports dark/light theme switching via Tailwind's `dark:` variant prefix — the `dark` class is toggled on `<html>` by `ThemeToggle.astro`.

---

## Theme Architecture

| Mechanism | Detail |
|-----------|--------|
| Strategy | Tailwind `class` dark mode (`darkMode: 'class'` in `tailwind.config.mjs`) |
| Toggle | `<ThemeToggle />` writes `dark` / `light` to `localStorage` and toggles `html.dark` |
| FOUC prevention | Inline `<script is:inline>` in `BaseLayout.astro` `<head>` reads `localStorage` synchronously before CSS renders |
| CSS tokens | `src/styles/design-tokens.css` + legacy aliases in `global.css` under `html.dark {}` |

---

## Components

### Badge

**File:** `src/components/ui/Badge.astro`

Eyebrow labels used above section headings.

```astro
<Badge label="Why Choose Us" variant="primary" />
<Badge label="New Feature" variant="accent" />
<Badge label="Category" variant="secondary" />
```

| Variant | Light | Dark |
|---------|-------|------|
| `primary` (default) | `bg-primary-50 text-primary-700` | `bg-primary-900/40 text-primary-300` |
| `primary-dark` | `bg-primary-400/20 text-primary-300` | same (designed for dark sections) |
| `accent` | `bg-accent-50 text-accent-700` | `bg-accent-900/40 text-accent-300` |
| `secondary` | `bg-secondary-100 text-secondary-700` | `bg-secondary-800 text-secondary-300` |

> **Usage note:** Use `primary` or `accent` on light/surface sections. Use `primary-dark` on hero/CTA sections that have dark gradient backgrounds (these sections are dark in both themes).

---

### Card

**File:** `src/components/ui/Card.astro`

Versatile content container with predefined style variants.

```astro
<Card variant="feature">...</Card>
<Card variant="service" padding="p-8">...</Card>
<Card variant="surface">...</Card>
<Card variant="dark">...</Card>  <!-- for use on dark gradient sections -->
<Card variant="plain">...</Card> <!-- no styles applied -->
```

| Variant | Light | Dark |
|---------|-------|------|
| `feature` | `from-secondary-50 to-white`, border `secondary-100` | `from-secondary-800 to-secondary-900`, border `secondary-700` |
| `service` | `bg-white`, border `secondary-100` | `bg-secondary-800`, border `secondary-700` |
| `surface` | `bg-secondary-50`, border `secondary-200` | `bg-secondary-800`, border `secondary-700` |
| `dark` | `bg-white/5` glassmorphism (static) | same — designed for dark gradient backgrounds only |

---

### SectionHeader

**File:** `src/components/ui/SectionHeader.astro`

Standard eyebrow + heading + description pattern used in every section.

```astro
<!-- On light/surface sections -->
<SectionHeader
  badge="Our Services"
  title="What We Build"
  description="From concept to production."
  theme="light"
  badgeColor="primary"
/>

<!-- On dark/hero sections -->
<SectionHeader
  badge="How It Works"
  title="Simple Process"
  theme="dark"
  badgeColor="accent"
/>
```

| Prop | Type | Default | Notes |
|------|------|---------|-------|
| `badge` | `string` | required | Eyebrow label text |
| `title` | `string` | required | `<h2>` heading |
| `description` | `string` | — | Optional paragraph below heading |
| `theme` | `'light' \| 'dark'` | `'light'` | Controls text/badge colors |
| `badgeColor` | `'primary' \| 'accent'` | `'primary'` | Badge hue |
| `maxWidth` | `string` | `'max-w-3xl'` | Tailwind width class |

**Theme behavior:**

- `theme="light"` — heading `text-secondary-900 dark:text-secondary-50`, description `text-secondary-600 dark:text-secondary-400`
- `theme="dark"` — heading `text-white`, description `text-secondary-300` (used on dark gradient backgrounds that look the same in both themes)

---

### ThemeToggle

**File:** `src/components/ThemeToggle.astro`

Sun/moon icon button that toggles between dark and light mode.

```astro
<ThemeToggle />
```

- Persists preference in `localStorage` under key `theme` (`'dark'` | `'light'`)
- Falls back to `prefers-color-scheme` when no stored preference
- Updates `meta[name="theme-color"]` for browser chrome color
- Fully keyboard accessible — ARIA label updates dynamically
- Respects `prefers-reduced-motion`

---

### Header

**File:** `src/components/Header.astro`

Fixed top navigation with desktop menu, mobile slide-out panel, and theme toggle.

```astro
<Header />  <!-- used in BaseLayout, no props needed -->
```

**Dark mode classes:**

| Element | Light | Dark |
|---------|-------|------|
| Header bar | `bg-white/95 border-secondary-100` | `bg-secondary-900/95 border-secondary-800` |
| Active nav link | `text-primary bg-primary-50` | `text-primary-400 bg-primary-900/30` |
| Inactive nav link hover | `hover:bg-secondary-50` | `dark:hover:bg-secondary-800` |
| Mobile panel | `bg-white` | `bg-secondary-900` |
| Mobile nav items | same pattern as desktop | same dark variants |

---

### Footer

**File:** `src/components/Footer.astro`

Always dark (`bg-secondary-900`) — no light/dark switching needed as the footer is intentionally dark in both modes.

---

### LazyImage

**File:** `src/components/LazyImage.astro`

Lightweight image wrapper with native lazy loading and fade-in animation.

```astro
<LazyImage
  src="/images/hero.jpg"
  alt="Team working"
  width={1200}
  height={630}
  loading="eager"
  fetchpriority="high"
/>
```

| Prop | Default | Notes |
|------|---------|-------|
| `loading` | `'lazy'` | Use `'eager'` for above-the-fold images |
| `fetchpriority` | `'auto'` | Use `'high'` for LCP images |
| `placeholder` | `var(--color-surface-alt)` | Adapts to theme via CSS custom property |

The placeholder color uses `--color-surface-alt` from `global.css`, which is `#f1f5f9` in light mode and `#1e293b` in dark mode.

---

## Global CSS Component Classes

Classes defined in `src/styles/global.css` under `@layer components`. All support dark mode via `dark:` variants.

### Buttons

```html
<button class="btn-primary">Primary Action</button>
<button class="btn-primary-lg">Large CTA</button>
<button class="btn-secondary">Secondary</button>
<button class="btn-accent">Accent</button>
<button class="btn-ghost">Ghost (for dark sections)</button>
<button class="btn-inverse-lg">Inverse Large (for dark sections)</button>
```

| Class | Theme behavior |
|-------|---------------|
| `btn-primary` | Cyan background — same in both modes (brand color) |
| `btn-secondary` | `border-secondary` in light / `border-secondary-400 text-secondary-300` in dark |
| `btn-ghost` | `bg-white/5` — designed for dark sections only |

### Badges (global classes)

```html
<span class="badge-primary">Label</span>
<span class="badge-accent">Label</span>
<span class="badge-secondary">Label</span>
<span class="badge-primary-dark">Label</span>
```

### Cards (global classes)

```html
<div class="card">...</div>
<div class="card-hover">...</div>
<div class="card-service">...</div>
<div class="card-surface">...</div>
```

### Forms

```html
<label class="form-label">Email</label>
<input class="form-input" type="email" />
<p class="form-error">Required field</p>
```

| Class | Dark mode |
|-------|-----------|
| `form-input` | `bg-secondary-800 border-secondary-600 text-secondary-100` |
| `form-label` | `text-secondary-300` |
| `form-error` | `text-red-400` |

### Section Typography

```html
<h2 class="section-title">Heading</h2>
<p class="section-description">Supporting text</p>

<!-- On dark gradient sections -->
<h2 class="section-title-inverse">Heading</h2>
<p class="section-description-inverse">Supporting text</p>
```

---

## Design Tokens Quick Reference

Defined in `src/styles/design-tokens.css` and aliased in `global.css`.

| Token | Light value | Dark value |
|-------|-------------|------------|
| `--color-surface` | `#f8fafc` | `#0f172a` |
| `--color-surface-alt` | `#f1f5f9` | `#1e293b` |
| `--color-border` | `#e2e8f0` | `#334155` |
| `--color-text-primary` | `#1e293b` | `#f1f5f9` |
| `--color-text-secondary` | `#475569` | `#cbd5e1` |
| `--color-text-muted` | `#94a3b8` | `#94a3b8` |
| `--color-primary` | `#0891b2` (cyan-600) | `#22d3ee` (cyan-400) |
| `--color-accent` | `#f59e0b` (amber-500) | `#fbbf24` (amber-400) |

---

## Adding a New Component

1. Use `dark:` prefixed Tailwind classes for all color utilities
2. For surface backgrounds: `bg-white dark:bg-secondary-800` or `bg-secondary-50 dark:bg-secondary-800`
3. For borders: `border-secondary-100 dark:border-secondary-700`
4. For text: `text-secondary-900 dark:text-secondary-50` (headings), `text-secondary-600 dark:text-secondary-400` (body)
5. Do NOT use `html.dark` CSS overrides — prefer Tailwind `dark:` variants for colocation
6. Use CSS custom properties (`var(--color-surface)`) only when Tailwind classes won't work (e.g. dynamic inline styles)
