47c71e6f54
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/
416 lines
12 KiB
Markdown
416 lines
12 KiB
Markdown
# 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
|