feat(ui): complete Task 4 UI redesign — all sub-tasks 1-10
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 8m47s

- Implemented complete design system with 40+ CSS custom properties
- Created 9 UI primitives (GameCard, SectionHeader, StatRow, ManaBar, ElementBadge, ValueDisplay, ActionButton, SkillRow, TooltipInfo)
- Redesigned all tabs: Spire, Skills, Stats, Equipment, Crafting, Attunements, Golemancy, Spells, Loot, Achievements, Lab, Debug
- Added toast notification system (GameToast) with success/warning/error/info types
- Added confirmation dialogs for destructive actions
- Removed all dev artifacts and component name labels
- Added empty states to all tabs
- Replaced emoji icons with Lucide React icons
- Added enchantPower placeholder to StatsTab and EquipmentTab
- Mobile audit passed at 375px viewport
- Build passes with 0 errors, lint passes with 0 errors

Sub-tasks completed:
- ST1: Design System Implementation
- ST2: Global Layout & Header
- ST3: Left Panel (Mana Display & Action Area)
- ST4: Skills Tab
- ST5: Spire Tab & Spire Mode UI
- ST6: Stats Tab
- ST7: Equipment & Crafting Tabs
- ST8: Attunements Tab
- ST9: Remaining Tabs
- ST10: Toast System & Confirmation Dialogs

Documentation: 15+ files in docs/task4/
This commit is contained in:
Refactoring Agent
2026-04-28 11:38:45 +02:00
parent 3c29c1c834
commit 47c71e6f54
61 changed files with 6892 additions and 1842 deletions
+415
View File
@@ -0,0 +1,415 @@
# Mana Loop - Design System
## Version: 1.0
## Date: 2024-04-27
---
## 1. Visual Identity
### Theme: Ancient Arcane Grimoire
The Mana Loop UI should feel like an ancient spellbook infused with crystalline magic - not a generic dark mode SaaS application.
**Aesthetic References:**
- Path of Exile passive tree (dark, arcane, intricate)
- Slay the Spire card UI (clear, readable, atmospheric)
- Hades menu screens (bold, high-contrast, mythological)
**Guiding Principles:**
1. Every UI region should feel like it belongs in the world
2. Restraint over decoration: one strong texture/treatment per region
3. The UI must stay fast and readable - this is an idle game
4. No generic purple-gradient-on-charcoal
**Key Visual Elements:**
- Illuminated manuscript styling for headers (gold accents, serif fonts)
- Crystalline magic effects for interactive elements
- Subtle arcane patterns as background texture
- High contrast for readability with muted atmospheric colors
---
## 2. Color Tokens
### 2a. Background Colors (Depth Levels)
```css
--bg-base: #060811; /* Outermost / page - deep void black */
--bg-surface: #0C1020; /* Panels, cards - dark navy */
--bg-elevated: #111628; /* Dropdowns, tooltips, modals - medium dark */
--bg-sunken: #181f35; /* Inset wells, progress track - lighter panel */
```
### 2b. Border Colors
```css
--border-subtle: #1e2a45; /* Barely-there separators */
--border-default: #2a3a60; /* Standard card edges */
--border-focus: #5B8FFF; /* Interactive focus rings */
```
### 2c. Text Colors
```css
--text-primary: #c8d8f8; /* Main text - light blue-white */
--text-secondary: #7a92c0; /* Secondary text - muted blue-gray */
--text-muted: #4a5f8a; /* Muted text - darker blue-gray */
--text-disabled: #2a3a60; /* Disabled text - very muted */
```
### 2d. Mana Element Colors
Each mana type has a distinct, semantic color that reflects its nature:
```css
--mana-fire: #E8734A; /* Ember orange-red */
--mana-water: #3BAFDA; /* Deep teal */
--mana-air: #C8D8F8; /* Silver-white */
--mana-earth: #B8860B; /* Warm ochre */
--mana-light: #D4A843; /* Gold */
--mana-dark: #4B0082; /* Deep indigo */
--mana-death: #8B7D8B; /* Muted violet-grey */
--mana-transfer: #00CED1; /* Cyan - the "tech mana" */
--mana-metal: #708090; /* Cool steel */
--mana-sand: #C2B280; /* Warm tan */
--mana-lightning: #FFD700; /* Electric yellow */
--mana-crystal: #B0E0E6; /* Pale ice blue */
--mana-stellar: #FF8C00; /* Bright amber */
--mana-void: #1A0A2E; /* Deep black-purple */
```
### 2e. Semantic UI Colors
```css
--color-success: #27AE60; /* Green */
--color-warning: #F39C12; /* Orange */
--color-danger: #C0392B; /* Red */
--color-info: #3B6FE8; /* Blue */
```
### 2f. Interactive Colors
```css
--interactive-primary: #3B6FE8; /* Main CTA - Gather, Study, Climb */
--interactive-primary-hover: #5B8FFF; /* Hover state */
--interactive-secondary: #2a3a60; /* Secondary actions */
--interactive-secondary-hover: #3a4a70; /* Secondary hover */
--interactive-danger: #C0392B; /* Danger actions */
--interactive-danger-hover: #E74C3C; /* Danger hover */
--interactive-disabled: #1e2a45; /* Disabled state */
```
---
## 3. Typography
### 3a. Font Stack
```css
--font-heading: 'Cinzel', serif; /* Fantasy-adjacent serif for headers */
--font-body: 'Crimson Text', Georgia, serif; /* All body copy */
--font-mono: 'JetBrains Mono', monospace; /* Numbers, values, timers */
```
### 3b. Type Scale
| Size | Font Size | Line Height | Letter Spacing | Usage |
|------|-----------|--------------|----------------|-------|
| xs | 0.75rem (12px) | 1rem | 0.05em | Captions, labels |
| sm | 0.875rem (14px) | 1.25rem | 0.025em | Secondary text |
| base | 1rem (16px) | 1.5rem | normal | Body text |
| lg | 1.125rem (18px) | 1.75rem | normal | Emphasized text |
| xl | 1.25rem (20px) | 1.75rem | -0.025em | Subheaders |
| 2xl | 1.5rem (24px) | 2rem | -0.05em | Section headers |
| 3xl | 1.875rem (30px) | 2.25rem | -0.05em | Page titles |
**Heading Specifics:**
- Font: `--font-heading` (Cinzel)
- Letter spacing: 0.05em to 0.1em
- Text transform: uppercase for game panel titles
- Font weight: 600 or 700
---
## 4. Spacing & Layout
### 4a. Base Unit
- **4px** (Tailwind default: 1 unit = 0.25rem)
### 4b. Border Radius
```css
--radius: 0.5rem; /* 8px - used everywhere for consistency */
```
### 4c. Panel Inner Padding
- All tabs/panels: `1.5rem` (24px / p-6 in Tailwind)
- Card content: `1rem` (16px / p-4 in Tailwind)
- Tight spacing: `0.75rem` (12px / p-3 in Tailwind)
### 4d. Gaps
- Between cards: `1rem` (16px / gap-4)
- Between elements: `0.5rem` (8px / gap-2)
- Tight elements: `0.25rem` (4px / gap-1)
---
## 5. Component Primitives
### 5a. GameCard
**Purpose:** All panel/section wrappers
**Variants:** default, elevated, sunken, danger
**Props:** `variant`, `className`, `children`
```typescript
interface GameCardProps {
variant?: 'default' | 'elevated' | 'sunken' | 'danger';
className?: string;
children: React.ReactNode;
}
```
**Styling:**
- default: `--bg-surface` background, `--border-default` border
- elevated: `--bg-elevated` background, stronger shadow
- sunken: `--bg-sunken` background, inset appearance
- danger: Red-tinted border for warning states
### 5b. SectionHeader
**Purpose:** Consistent section titles with optional right-side action slot
**Props:** `title`, `action`, `className`
```typescript
interface SectionHeaderProps {
title: string;
action?: React.ReactNode;
className?: string;
}
```
**Styling:**
- Font: `--font-heading`
- Text transform: uppercase
- Letter spacing: 0.1em
- Color: `--text-primary`
- Optional right-side action slot for buttons/badges
### 5c. StatRow
**Purpose:** Label + value pair
**Props:** `label`, `value`, `highlight`, `className`
```typescript
interface StatRowProps {
label: string;
value: string | number;
highlight?: 'default' | 'success' | 'warning' | 'danger' | 'mana-*';
className?: string;
}
```
**Styling:**
- Label: `--text-secondary`, left-aligned
- Value: `--text-primary`, right-aligned, `--font-mono`
- Highlight colors change value text color
### 5d. ManaBar
**Purpose:** Progress bar skinned per mana type
**Props:** `value`, `max`, `manaType`, `className`
```typescript
interface ManaBarProps {
value: number;
max: number;
manaType?: keyof typeof MANA_COLORS;
className?: string;
}
```
**Styling:**
- Height: 8px (h-2)
- Border radius: `--radius`
- Fill uses appropriate `--mana-*` color
- Transition: 300ms ease-out
- Background: `--bg-sunken`
### 5e. ElementBadge
**Purpose:** Pill badge for mana/element type with matching icon + color
**Props:** `element`, `showIcon`, `size`, `className`
```typescript
interface ElementBadgeProps {
element: string;
showIcon?: boolean;
size?: 'sm' | 'md';
className?: string;
}
```
**Styling:**
- Pill shape (rounded-full)
- Background: `--mana-{type}` at 20% opacity
- Border: `--mana-{type}` at 60% opacity
- Text: `--mana-{type}` full color
- Icon from Lucide icons matching element
### 5f. ValueDisplay
**Purpose:** Animated numeric display for mana, DPS, etc.
**Props:** `value`, `label`, `color`, `className`
```typescript
interface ValueDisplayProps {
value: number;
label?: string;
color?: string;
className?: string;
}
```
**Styling:**
- Font: `--font-mono`
- Font feature: `tabular-nums` for aligned digits
- Transition on value change (CSS only)
- Optional label below in `--text-secondary`
### 5g. ActionButton
**Purpose:** Primary game CTA
**Variants:** primary, secondary, danger, ghost
**Props:** `variant`, `size`, `disabled`, `children`, `className`
```typescript
interface ActionButtonProps {
variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
children: React.ReactNode;
className?: string;
}
```
**Styling:**
- primary: `--interactive-primary` background
- secondary: `--interactive-secondary` background
- danger: `--interactive-danger` background
- ghost: Transparent with border
- Hover: 100ms ease transition
- Disabled: `--interactive-disabled` with reduced opacity
### 5h. SkillRow
**Purpose:** Standard skill entry row
**Props:** `skill`, `onStudy`, `onUpgrade`, `children`, `className`
```typescript
interface SkillRowProps {
skill: Skill;
onStudy?: () => void;
onUpgrade?: () => void;
children?: React.ReactNode;
className?: string;
}
```
**Styling:**
- Name: `--text-primary`, `--font-heading`
- Description: `--text-secondary`, `--font-body`
- Cost: `--text-muted`, `--font-mono`
- Level dots: Using `--mana-purple` for filled
- Study button: ActionButton (secondary variant)
### 5i. TooltipInfo
**Purpose:** Consistent tooltip triggered by `?` icon
**Props:** `content`, `children`, `className`
```typescript
interface TooltipInfoProps {
content: string;
children?: React.ReactNode;
className?: string;
}
```
**Styling:**
- Trigger: `?` icon in circle, `--text-muted`
- Content: `--bg-elevated` background, `--text-primary` text
- Uses Radix Tooltip under the hood
- Delay: 0ms (instant)
---
## 6. Animation Budget
| Category | Rule | Duration | Easing |
|----------|------|----------|--------|
| Mana bar fill | CSS transition | 300ms | ease-out |
| Progress bars (study/cast) | CSS transition | linear | linear |
| Tab switch | CSS transition | 150ms | fade-in |
| Hover states | CSS transition | 100ms | ease |
| Number changes | CSS `tabular-nums` | N/A | N/A |
| Idle sparkle / glow | One subtle glow pulse on Gather button ONLY | 2s | ease-in-out, infinite |
| Spire combat | Cast bar animates smoothly | 300ms | ease-out |
**Important Notes:**
- NO framer-motion for layout shifts - CSS transitions only
- All animations must be performant (idle game runs constantly)
- Respect `prefers-reduced-motion` setting
---
## 7. Icon System
**Library:** Lucide React (already installed)
**Usage Guidelines:**
- No emoji in UI - use Lucide icons only
- Icons should match mana element colors when applicable
- Standard sizes: 16px (sm), 20px (md), 24px (lg)
- Stroke width: 2 (default)
**Common Icons:**
- Mana: Zap, Flame, Droplet, Wind, Mountain, Sun, Moon, Skull, etc.
- Actions: Play, Pause, RotateCcw, ChevronRight, etc.
- UI: Settings, Info, AlertTriangle, Check, X, etc.
---
## 8. Z-Index Scale
| Layer | Value | Usage |
|-------|-------|-------|
| Base | 0 | Normal content |
| Dropdown | 50 | Select, dropdown menus |
| Sticky | 100 | Sticky headers |
| Overlay | 200 | Modals, dialogs |
| Toast | 300 | Toast notifications |
| Tooltip | 400 | Tooltips |
---
## 9. Shadow System
```css
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.5);
--shadow-glow-gold: 0 0 15px rgba(212, 168, 67, 0.4);
--shadow-glow-purple: 0 0 15px rgba(124, 92, 191, 0.4);
--shadow-glow-accent: 0 0 15px rgba(60, 111, 232, 0.4);
```
---
## 10. Implementation Checklist
- [ ] Update `src/app/globals.css` with all CSS custom properties
- [ ] Create `src/components/ui/game-card.tsx`
- [ ] Create `src/components/ui/section-header.tsx`
- [ ] Create `src/components/ui/stat-row.tsx`
- [ ] Create `src/components/ui/mana-bar.tsx`
- [ ] Create `src/components/ui/element-badge.tsx`
- [ ] Create `src/components/ui/value-display.tsx`
- [ ] Create `src/components/ui/action-button.tsx` (or update existing button.tsx)
- [ ] Create `src/components/ui/skill-row.tsx`
- [ ] Create `src/components/ui/tooltip-info.tsx`
- [ ] Update `src/components/ui/index.ts` with all exports
- [ ] Search and remove component name labels
- [ ] Create all sub-task documentation files
- [ ] Run final lint verification