feat: add collapsible skill categories in SkillsTab
Some checks failed
Build and Publish Mana Loop Docker Image / build-and-publish (push) Has been cancelled

- Add collapsedCategories state to track which categories are collapsed
- Add toggleCategory function to toggle collapse state
- Update CardHeader to be clickable for collapse/expand
- Show ChevronDown/ChevronRight icons based on collapse state
- Show skill count badge in each category header
This commit is contained in:
2026-03-27 18:58:52 +00:00
parent 4748b81fe6
commit c341d3de80

View File

@@ -14,6 +14,7 @@ import { Badge } from '@/components/ui/badge';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { StudyProgress } from './StudyProgress';
import { UpgradeDialog } from './UpgradeDialog';
import { ChevronDown, ChevronRight } from 'lucide-react';
export interface SkillsTabProps {
store: GameStore;
@@ -55,10 +56,24 @@ export function SkillsTab({ store }: SkillsTabProps) {
const [upgradeDialogSkill, setUpgradeDialogSkill] = useState<string | null>(null);
const [upgradeDialogMilestone, setUpgradeDialogMilestone] = useState<5 | 10>(5);
const [pendingUpgradeSelections, setPendingUpgradeSelections] = useState<string[]>([]);
const [collapsedCategories, setCollapsedCategories] = useState<Set<string>>(new Set());
const studySpeedMult = getStudySpeedMultiplier(store.skills);
const upgradeEffects = getUnifiedEffects(store);
// Toggle category collapse
const toggleCategory = (categoryId: string) => {
setCollapsedCategories(prev => {
const newSet = new Set(prev);
if (newSet.has(categoryId)) {
newSet.delete(categoryId);
} else {
newSet.add(categoryId);
}
return newSet;
});
};
// Get upgrade choices for dialog
const getUpgradeChoices = () => {
if (!upgradeDialogSkill) return { available: [] as SkillUpgradeChoice[], selected: [] as string[] };
@@ -138,13 +153,20 @@ export function SkillsTab({ store }: SkillsTabProps) {
const skillsInCat = Object.entries(SKILLS_DEF).filter(([, def]) => def.cat === cat.id);
if (skillsInCat.length === 0) return null;
const isCollapsed = collapsedCategories.has(cat.id);
return (
<Card key={cat.id} className="bg-gray-900/80 border-gray-700">
<CardHeader className="pb-2">
<CardTitle className="text-amber-400 game-panel-title text-xs">
{cat.icon} {cat.name}
<CardHeader className="pb-2 cursor-pointer" onClick={() => toggleCategory(cat.id)}>
<CardTitle className="text-amber-400 game-panel-title text-xs flex items-center justify-between">
<span>{cat.icon} {cat.name}</span>
<div className="flex items-center gap-2">
<Badge variant="outline" className="text-xs">{skillsInCat.length} skills</Badge>
{isCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
</div>
</CardTitle>
</CardHeader>
{!isCollapsed && (
<CardContent>
<div className="space-y-2">
{skillsInCat.map(([id, def]) => {
@@ -337,6 +359,7 @@ export function SkillsTab({ store }: SkillsTabProps) {
})}
</div>
</CardContent>
)}
</Card>
);
});