Files
Mana-Loop/src/components/game/layout/TabBar.tsx
T
n8n-gitea 3e5b634815
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 42s
feat: partial UI redesign - TabBar, ManaDisplay, StatsTab sub-sections
Design token migration:
- TabBar: replaced hardcoded colors/shadows with --bg-panel, --border-subtle,
  --font-display tokens. Removed rounded-full pills, added Cinzel font tracking.
- ManaDisplay: replaced bg-gray-900/text-blue-400 with --mana-raw, --bg-panel,
  element-specific --mana-* tokens. Updated progress bar styling.
- StatsTab/* (all 7 sub-sections): replaced hardcoded gray/red/blue color values
  with semantic design tokens (--bg-panel, --border-subtle, --text-muted,
  element-themed mana colors)

NOTE: This is a partial implementation. TASK-011 paused to address
foundational issues (missing types, duplicate stat functions) first.
See issue #14 for full context.
2026-05-14 12:03:09 +02:00

143 lines
4.7 KiB
TypeScript

'use client';
import { useState } from 'react';
import { TabsTrigger } from '@/components/ui/tabs';
import { Separator } from '@/components/ui/separator';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import {
Mountain,
Sparkles,
Brain,
Wand2,
Bone,
Shield,
Hammer,
Gem,
Trophy,
FlaskConical,
BarChart3,
BookOpen,
Wrench
} from 'lucide-react';
interface TabBarProps {
activeTab: string;
onTabChange: (value: string) => void;
isMobile?: boolean;
}
// Tab configuration with groups
const TAB_GROUPS = [
{
name: 'World',
tabs: [
{ value: 'spire', label: 'Spire', icon: Mountain, mobileLabel: 'Spire' },
{ value: 'attunements', label: 'Attune', icon: Sparkles, mobileLabel: 'Attune' },
]
},
{
name: 'Power',
tabs: [
{ value: 'skills', label: 'Skills', icon: Brain, mobileLabel: 'Skills' },
{ value: 'spells', label: 'Spells', icon: Wand2, mobileLabel: 'Spells' },
{ value: 'golemancy', label: 'Golems', icon: Bone, mobileLabel: 'Golems' },
]
},
{
name: 'Gear',
tabs: [
{ value: 'equipment', label: 'Gear', icon: Shield, mobileLabel: 'Gear' },
{ value: 'crafting', label: 'Craft', icon: Hammer, mobileLabel: 'Craft' },
{ value: 'loot', label: 'Loot', icon: Gem, mobileLabel: 'Loot' },
]
},
{
name: 'Meta',
tabs: [
{ value: 'achievements', label: 'Achieve', icon: Trophy, mobileLabel: 'Achieve' },
{ value: 'stats', label: 'Stats', icon: BarChart3, mobileLabel: 'Stats' },
{ value: 'debug', label: 'Debug', icon: Wrench, mobileLabel: 'Debug' },
]
}
];
export function TabBar({ activeTab, onTabChange, isMobile = false }: TabBarProps) {
if (isMobile) {
return (
<TooltipProvider>
<div className="flex overflow-x-auto scrollbar-thin gap-1 pb-2" style={{ flexWrap: 'nowrap' }}>
{TAB_GROUPS.map((group, groupIndex) => (
<div key={group.name} className="flex items-center flex-shrink-0">
{groupIndex > 0 && (
<Separator orientation="vertical" className="h-6 mx-1 bg-[var(--border-subtle)]" />
)}
{group.tabs.map((tab) => {
const Icon = tab.icon;
const isActive = activeTab === tab.value;
return (
<Tooltip key={tab.value}>
<TooltipTrigger asChild>
<button
onClick={() => onTabChange(tab.value)}
className={`
flex items-center justify-center p-2 flex-shrink-0 transition-all border text-[var(--font-display)]
${isActive
? 'border-[var(--border-accent)] bg-[var(--bg-raised)] text-[var(--interactive-primary)]'
: 'border-transparent text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-panel)] hover:border-[var(--border-subtle)]'
}
`}
aria-label={tab.label}
>
<Icon className="w-5 h-5" />
</button>
</TooltipTrigger>
<TooltipContent side="bottom">
<p>{tab.label}</p>
</TooltipContent>
</Tooltip>
);
})}
</div>
))}
</div>
</TooltipProvider>
);
}
// Desktop view - grouped tabs with separators
return (
<div className="flex items-center gap-1 w-full" style={{ flexWrap: 'nowrap' }}>
{TAB_GROUPS.map((group, groupIndex) => (
<div key={group.name} className="flex items-center flex-shrink-0">
{groupIndex > 0 && (
<Separator orientation="vertical" className="h-6 mx-2 bg-[var(--border-subtle)]" />
)}
{group.tabs.map((tab) => {
const isActive = activeTab === tab.value;
return (
<TabsTrigger
key={tab.value}
value={tab.value}
className={`
text-xs px-3 py-1.5 relative transition-all whitespace-nowrap text-[var(--font-display)] tracking-wider
${isActive
? 'text-[var(--interactive-primary)]'
: 'text-[var(--text-secondary)] hover:text-[var(--text-primary)]'
}
`}
style={isActive ? {
borderBottom: '2px solid var(--border-accent)',
} : {}}
>
{tab.label}
</TabsTrigger>
);
})}
</div>
))}
</div>
);
}
TabBar.displayName = "TabBar";