Files
Mana-Loop/docs/task4/design_system.md
T
Refactoring Agent 47c71e6f54
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 8m47s
feat(ui): complete Task 4 UI redesign — all sub-tasks 1-10
- 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/
2026-04-28 11:38:45 +02:00

12 KiB

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)

--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

--border-subtle: #1e2a45;   /* Barely-there separators */
--border-default: #2a3a60;  /* Standard card edges */
--border-focus: #5B8FFF;    /* Interactive focus rings */

2c. Text Colors

--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:

--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

--color-success: #27AE60;    /* Green */
--color-warning: #F39C12;   /* Orange */
--color-danger: #C0392B;     /* Red */
--color-info: #3B6FE8;      /* Blue */

2f. Interactive Colors

--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

--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

--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

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

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

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

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

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

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

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

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

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

--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