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
+100
View File
@@ -0,0 +1,100 @@
import * as React from "react";
import { cn } from "@/lib/utils";
import { Check, Circle, ArrowRight } from "lucide-react";
interface StepperProps extends React.HTMLAttributes<HTMLDivElement> {
steps: string[];
currentStep: number; // 0-indexed
orientation?: "horizontal" | "vertical";
}
interface StepProps {
label: string;
stepNumber: number;
isActive: boolean;
isCompleted: boolean;
isLast: boolean;
orientation?: "horizontal" | "vertical";
}
const Step = ({ label, stepNumber, isActive, isCompleted, isLast, orientation = "horizontal" }: StepProps) => {
return (
<div
className={cn(
"flex items-center",
orientation === "vertical" ? "flex-col" : "flex-row",
orientation === "vertical" && "w-full"
)}
>
<div className="flex flex-col items-center">
<div
className={cn(
"flex items-center justify-center w-8 h-8 rounded-full border-2 transition-all duration-200",
isActive && "border-[var(--interactive-primary)] bg-[var(--interactive-primary)]/20 text-[var(--interactive-primary)]",
isCompleted && "border-[var(--color-success)] bg-[var(--color-success)]/20 text-[var(--color-success)]",
!isActive && !isCompleted && "border-[var(--border-default)] bg-[var(--bg-sunken)] text-[var(--text-muted)]"
)}
aria-current={isActive ? "step" : undefined}
>
{isCompleted ? (
<Check size={16} />
) : (
<span className="text-xs font-semibold">{stepNumber}</span>
)}
</div>
<span
className={cn(
"text-xs mt-1 font-medium",
isActive && "text-[var(--interactive-primary)]",
isCompleted && "text-[var(--color-success)]",
!isActive && !isCompleted && "text-[var(--text-muted)]"
)}
>
{label}
</span>
</div>
{!isLast && (
<div
className={cn(
"flex-1 mx-2",
orientation === "vertical" ? "h-8 w-px my-1" : "h-px",
isCompleted ? "bg-[var(--color-success)]" : "bg-[var(--border-default)]"
)}
/>
)}
</div>
);
};
export function Stepper({ steps, currentStep, orientation = "horizontal", className, ...props }: StepperProps) {
return (
<div
data-slot="stepper"
className={cn(
"flex w-full",
orientation === "horizontal" ? "flex-row items-center" : "flex-col",
className
)}
role="list"
aria-label="Progress steps"
{...props}
>
{steps.map((step, index) => (
<div
key={step}
className={cn("flex items-center", orientation === "vertical" && "w-full")}
role="listitem"
>
<Step
label={step}
stepNumber={index + 1}
isActive={index === currentStep}
isCompleted={index < currentStep}
isLast={index === steps.length - 1}
orientation={orientation}
/>
</div>
))}
</div>
);
}