Latest Updated Pages
E2E Test Suite / Critical User Journeys (push) Has been skipped
E2E Test Suite / API Integration Tests (push) Has been skipped
Deploy to Production / Build & Verify (push) Failing after 13s
Ping Search Engines / Notify Search Engines (push) Successful in 3s
Deploy to Production / Pre-Deploy Tests (push) Has been skipped
Deploy to Production / Deploy to Railway (push) Has been skipped
Deploy to Production / Deploy to Render (push) Has been skipped
Deploy to Production / Deploy to VPS (PM2) (push) Has been skipped
Deploy to Production / Deploy to Fly.io (push) Has been skipped
Deploy to Production / Post-Deploy Verification (push) Has been skipped
Deploy to Production / Notify on Failure (push) Successful in 1s
E2E Test Suite / Smoke Tests (P0) (push) Failing after 9m36s
E2E Test Suite / Form Interaction Tests (push) Failing after 12m6s
E2E Test Suite / Destructive & Chaos Tests (push) Failing after 11m46s
E2E Test Suite / Cross-Browser Regression (chromium) (push) Failing after 9m31s
E2E Test Suite / Cross-Browser Regression (firefox) (push) Failing after 11m5s
E2E Test Suite / Cross-Browser Regression (webkit) (push) Failing after 15m24s
E2E Test Suite / Security Header Tests (push) Failing after 7m55s
E2E Test Suite / Test Report Summary (push) Failing after 6s
E2E Test Suite / Mobile Device Tests (push) Failing after 3h12m28s
Uptime Monitor / Health & Response Time (push) Successful in 5s
Uptime Monitor / SSL Certificate (push) Successful in 3s
Uptime Monitor / Send Alerts (push) Has been skipped
Uptime Monitor / Record Uptime Success (push) Successful in 2s

This commit is contained in:
2026-03-22 14:37:17 +05:30
parent d402256547
commit 0614ae6f85
80 changed files with 11667 additions and 687 deletions
@@ -0,0 +1,272 @@
# 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)