diff --git a/docs/circular-deps.txt b/docs/circular-deps.txt
index 2fd2b6a..1242411 100644
--- a/docs/circular-deps.txt
+++ b/docs/circular-deps.txt
@@ -1,8 +1,8 @@
# Circular Dependencies
-Generated: 2026-05-19T16:29:33.501Z
+Generated: 2026-05-19T18:19:35.896Z
Found: 3 circular chain(s) — these MUST be fixed before modifying involved files.
-1. Processed 121 files (1.3s) (4 warnings)
+1. Processed 121 files (1.2s) (4 warnings)
2. 1) data/equipment/index.ts > data/equipment/utils.ts
3. 2) data/golems/index.ts > data/golems/utils.ts
diff --git a/docs/dependency-graph.json b/docs/dependency-graph.json
index 5422abd..dd23d7e 100644
--- a/docs/dependency-graph.json
+++ b/docs/dependency-graph.json
@@ -1,6 +1,6 @@
{
"_meta": {
- "generated": "2026-05-19T16:29:32.045Z",
+ "generated": "2026-05-19T18:19:34.562Z",
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
"usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry."
},
diff --git a/docs/project-structure.txt b/docs/project-structure.txt
index b2b8f02..11b38db 100644
--- a/docs/project-structure.txt
+++ b/docs/project-structure.txt
@@ -97,6 +97,10 @@ Mana-Loop/
│ │ │ │ │ ├── GolemDebugSection.tsx
│ │ │ │ │ ├── PactDebugSection.tsx
│ │ │ │ │ └── SpireDebugSection.tsx
+│ │ │ │ ├── EquipmentTab/
+│ │ │ │ │ ├── EquipmentEffectsSummary.tsx
+│ │ │ │ │ ├── EquipmentSlotGrid.tsx
+│ │ │ │ │ └── InventoryList.tsx
│ │ │ │ ├── StatsTab/
│ │ │ │ │ ├── CombatStatsSection.tsx
│ │ │ │ │ ├── ElementStatsSection.tsx
@@ -111,6 +115,8 @@ Mana-Loop/
│ │ │ │ ├── DebugTab.test.ts
│ │ │ │ ├── DebugTab.tsx
│ │ │ │ ├── DisciplinesTab.tsx
+│ │ │ │ ├── EquipmentTab.test.ts
+│ │ │ │ ├── EquipmentTab.tsx
│ │ │ │ ├── PrestigeTab.test.ts
│ │ │ │ ├── PrestigeTab.tsx
│ │ │ │ ├── SpellsTab.tsx
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 4620805..28f132a 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -48,6 +48,7 @@ const DebugTab = lazy(() => import('@/components/game/tabs').then(module => ({ d
const AchievementsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.AchievementsTab })));
const AttunementsTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.AttunementsTab })));
const PrestigeTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.PrestigeTab })));
+const EquipmentTab = lazy(() => import('@/components/game/tabs').then(module => ({ default: module.EquipmentTab })));
const TabLoadingFallback = () =>
Loading...
;
@@ -241,6 +242,7 @@ export default function ManaLoopGame() {
⚗️ Attunements
🏆 Achievements
✨ Prestige
+ ⚔️ Equipment
@@ -302,6 +304,14 @@ export default function ManaLoopGame() {
+
+
+ equipment tab failed to load.}>
+ }>
+
+
+
+
diff --git a/src/components/game/tabs/EquipmentTab.test.ts b/src/components/game/tabs/EquipmentTab.test.ts
new file mode 100644
index 0000000..c35dca9
--- /dev/null
+++ b/src/components/game/tabs/EquipmentTab.test.ts
@@ -0,0 +1,215 @@
+import { describe, it, expect, vi } from 'vitest';
+
+// ─── Test: EquipmentTab barrel export ──────────────────────────────────────────
+
+describe('EquipmentTab module structure', () => {
+ it('exports EquipmentTab from barrel index', async () => {
+ const mod = await import('./EquipmentTab');
+ expect(mod.EquipmentTab).toBeDefined();
+ expect(typeof mod.EquipmentTab).toBe('function');
+ });
+
+ it('EquipmentTab has correct displayName', async () => {
+ const { EquipmentTab } = await import('./EquipmentTab');
+ expect(EquipmentTab.displayName).toBe('EquipmentTab');
+ });
+});
+
+// ─── Test: Barrel export includes EquipmentTab ─────────────────────────────────
+
+describe('Tab barrel export', () => {
+ it('includes EquipmentTab in the tabs index', async () => {
+ const mod = await import('@/components/game/tabs');
+ expect(mod.EquipmentTab).toBeDefined();
+ expect(typeof mod.EquipmentTab).toBe('function');
+ });
+});
+
+// ─── Test: Equipment slot definitions ──────────────────────────────────────────
+
+describe('Equipment slot definitions', () => {
+ it('has exactly 8 equipment slots', async () => {
+ const { EQUIPMENT_SLOTS } = await import('@/lib/game/data/equipment');
+ expect(EQUIPMENT_SLOTS).toHaveLength(8);
+ });
+
+ it('all slots have display names', async () => {
+ const { SLOT_NAMES, EQUIPMENT_SLOTS } = await import('@/lib/game/data/equipment');
+ for (const slot of EQUIPMENT_SLOTS) {
+ expect(SLOT_NAMES[slot]).toBeDefined();
+ expect(SLOT_NAMES[slot].length).toBeGreaterThan(0);
+ }
+ });
+
+ it('includes mainHand, offHand, head, body, hands, feet, accessory1, accessory2', async () => {
+ const { EQUIPMENT_SLOTS } = await import('@/lib/game/data/equipment');
+ expect(EQUIPMENT_SLOTS).toContain('mainHand');
+ expect(EQUIPMENT_SLOTS).toContain('offHand');
+ expect(EQUIPMENT_SLOTS).toContain('head');
+ expect(EQUIPMENT_SLOTS).toContain('body');
+ expect(EQUIPMENT_SLOTS).toContain('hands');
+ expect(EQUIPMENT_SLOTS).toContain('feet');
+ expect(EQUIPMENT_SLOTS).toContain('accessory1');
+ expect(EQUIPMENT_SLOTS).toContain('accessory2');
+ });
+});
+
+// ─── Test: Equipment type definitions ──────────────────────────────────────────
+
+describe('Equipment type definitions', () => {
+ it('all equipment types have required fields', async () => {
+ const { EQUIPMENT_TYPES } = await import('@/lib/game/data/equipment');
+ for (const [id, type] of Object.entries(EQUIPMENT_TYPES)) {
+ expect(type.id).toBe(id);
+ expect(type.name).toBeTruthy();
+ expect(type.category).toBeTruthy();
+ expect(type.slot).toBeTruthy();
+ expect(type.baseCapacity).toBeGreaterThan(0);
+ }
+ });
+
+ it('accessory category types can equip in accessory slots', async () => {
+ const { EQUIPMENT_TYPES, getValidSlotsForEquipmentType } = await import('@/lib/game/data/equipment');
+ const accessories = Object.values(EQUIPMENT_TYPES).filter((t) => t.category === 'accessory');
+ expect(accessories.length).toBeGreaterThan(0);
+ for (const acc of accessories) {
+ const slots = getValidSlotsForEquipmentType(acc);
+ expect(slots).toContain('accessory1');
+ expect(slots).toContain('accessory2');
+ }
+ });
+});
+
+// ─── Test: Starting equipment ──────────────────────────────────────────────────
+
+describe('Starting equipment', () => {
+ it('createStartingEquipment returns valid equippedInstances', async () => {
+ const { createStartingEquipment } = await import('@/lib/game/crafting-slice');
+ const { equippedInstances, equipmentInstances } = createStartingEquipment();
+
+ expect(equippedInstances.mainHand).toBeTruthy();
+ expect(equippedInstances.body).toBeTruthy();
+ expect(equippedInstances.feet).toBeTruthy();
+ expect(equippedInstances.offHand).toBeNull();
+ expect(equippedInstances.head).toBeNull();
+ expect(equippedInstances.hands).toBeNull();
+ expect(equippedInstances.accessory1).toBeNull();
+ expect(equippedInstances.accessory2).toBeNull();
+
+ expect(Object.keys(equipmentInstances).length).toBe(3);
+ });
+
+ it('starting equipment instances have valid fields', async () => {
+ const { createStartingEquipment } = await import('@/lib/game/crafting-slice');
+ const { equipmentInstances } = createStartingEquipment();
+
+ for (const instance of Object.values(equipmentInstances)) {
+ expect(instance.instanceId).toBeTruthy();
+ expect(instance.typeId).toBeTruthy();
+ expect(instance.name).toBeTruthy();
+ expect(instance.rarity).toBe('common');
+ expect(instance.quality).toBe(100);
+ expect(instance.usedCapacity).toBeGreaterThanOrEqual(0);
+ expect(instance.totalCapacity).toBeGreaterThan(0);
+ }
+ });
+});
+
+// ─── Test: Equipment actions ───────────────────────────────────────────────────
+
+describe('Equipment actions', () => {
+ it('equipItem is a function', async () => {
+ const { equipItem } = await import('@/lib/game/crafting-actions/equipment-actions');
+ expect(typeof equipItem).toBe('function');
+ });
+
+ it('unequipItem is a function', async () => {
+ const { unequipItem } = await import('@/lib/game/crafting-actions/equipment-actions');
+ expect(typeof unequipItem).toBe('function');
+ });
+
+ it('deleteEquipmentInstance is a function', async () => {
+ const { deleteEquipmentInstance } = await import('@/lib/game/crafting-actions/equipment-actions');
+ expect(typeof deleteEquipmentInstance).toBe('function');
+ });
+
+ it('createEquipmentInstance is a function', async () => {
+ const { createEquipmentInstance } = await import('@/lib/game/crafting-actions/equipment-actions');
+ expect(typeof createEquipmentInstance).toBe('function');
+ });
+});
+
+// ─── Test: Equipment effects ───────────────────────────────────────────────────
+
+describe('Equipment effects computation', () => {
+ it('computeEquipmentEffects returns empty for no equipment', async () => {
+ const { computeEquipmentEffects } = await import('@/lib/game/effects');
+ const result = computeEquipmentEffects({}, { mainHand: null, offHand: null, head: null, body: null, hands: null, feet: null, accessory1: null, accessory2: null });
+ expect(Object.keys(result.bonuses)).toHaveLength(0);
+ expect(Object.keys(result.multipliers)).toHaveLength(0);
+ expect(result.specials.size).toBe(0);
+ });
+
+ it('computeEquipmentEffects detects enchantment bonuses', async () => {
+ const { computeEquipmentEffects } = await import('@/lib/game/effects');
+ const instances = {
+ test1: {
+ instanceId: 'test1',
+ typeId: 'basicStaff',
+ name: 'Test Staff',
+ enchantments: [{ effectId: 'spell_manaBolt', stacks: 1, actualCost: 50 }],
+ usedCapacity: 50,
+ totalCapacity: 50,
+ rarity: 'common' as const,
+ quality: 100,
+ tags: [],
+ },
+ };
+ const equipped = { mainHand: 'test1', offHand: null, head: null, body: null, hands: null, feet: null, accessory1: null, accessory2: null };
+ const result = computeEquipmentEffects(instances, equipped);
+ // Should at least not crash and return a valid structure
+ expect(result).toHaveProperty('bonuses');
+ expect(result).toHaveProperty('multipliers');
+ expect(result).toHaveProperty('specials');
+ });
+});
+
+// ─── Test: File size limits ────────────────────────────────────────────────────
+
+describe('File size limits (400 lines max)', () => {
+ it('EquipmentTab.tsx is under 400 lines', async () => {
+ const fs = await import('fs');
+ const path = await import('path');
+ const filePath = path.join(__dirname, 'EquipmentTab.tsx');
+ const content = fs.readFileSync(filePath, 'utf-8');
+ const lines = content.split('\n').length;
+ expect(lines).toBeLessThan(400);
+ });
+
+ it('EquipmentSlotGrid.tsx is under 400 lines', async () => {
+ const fs = await import('fs');
+ const path = await import('path');
+ const filePath = path.join(__dirname, 'EquipmentTab/EquipmentSlotGrid.tsx');
+ const content = fs.readFileSync(filePath, 'utf-8');
+ const lines = content.split('\n').length;
+ expect(lines).toBeLessThan(400);
+ });
+
+ it('InventoryList.tsx is under 400 lines', async () => {
+ const fs = await import('fs');
+ const path = await import('path');
+ const filePath = path.join(__dirname, 'EquipmentTab/InventoryList.tsx');
+ const content = fs.readFileSync(filePath, 'utf-8');
+ const lines = content.split('\n').length;
+ expect(lines).toBeLessThan(400);
+ });
+
+ it('EquipmentEffectsSummary.tsx is under 400 lines', async () => {
+ const fs = await import('fs');
+ const path = await import('path');
+ const filePath = path.join(__dirname, 'EquipmentTab/EquipmentEffectsSummary.tsx');
+ const content = fs.readFileSync(filePath, 'utf-8');
+ const lines = content.split('\n').length;
+ expect(lines).toBeLessThan(400);
+ });
+});
diff --git a/src/components/game/tabs/EquipmentTab.tsx b/src/components/game/tabs/EquipmentTab.tsx
new file mode 100644
index 0000000..06fabd4
--- /dev/null
+++ b/src/components/game/tabs/EquipmentTab.tsx
@@ -0,0 +1,95 @@
+'use client';
+
+import { useState, useEffect, useCallback, useMemo } from 'react';
+import { useCraftingStore } from '@/lib/game/stores/craftingStore';
+import { equipItem, unequipItem, deleteEquipmentInstance } from '@/lib/game/crafting-actions/equipment-actions';
+import type { EquipmentSlot } from '@/lib/game/types';
+import { DebugName } from '@/components/game/debug/debug-context';
+import { EquipmentSlotGrid } from './EquipmentTab/EquipmentSlotGrid';
+import { InventoryList } from './EquipmentTab/InventoryList';
+import { EquipmentEffectsSummary } from './EquipmentTab/EquipmentEffectsSummary';
+
+export function EquipmentTab() {
+ const [mounted, setMounted] = useState(false);
+
+ const equippedInstances = useCraftingStore((s) => s.equippedInstances);
+ const equipmentInstances = useCraftingStore((s) => s.equipmentInstances);
+ const storeEquipItem = useCraftingStore((s) => s.equipItem);
+ const storeUnequipItem = useCraftingStore((s) => s.unequipItem);
+ const storeDeleteEquipment = useCraftingStore((s) => s.deleteEquipmentInstance);
+
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ const handleEquip = useCallback(
+ (instanceId: string, slot: EquipmentSlot) => {
+ storeEquipItem(instanceId, slot);
+ },
+ [storeEquipItem]
+ );
+
+ const handleUnequip = useCallback(
+ (slot: EquipmentSlot) => {
+ storeUnequipItem(slot);
+ },
+ [storeUnequipItem]
+ );
+
+ const handleDelete = useCallback(
+ (instanceId: string) => {
+ storeDeleteEquipment(instanceId);
+ },
+ [storeDeleteEquipment]
+ );
+
+ const inventoryItems = useMemo(
+ () =>
+ Object.entries(equipmentInstances).filter(
+ ([id]) => !Object.values(equippedInstances).includes(id)
+ ),
+ [equipmentInstances, equippedInstances]
+ );
+
+ if (!mounted) {
+ return (
+
+ Loading equipment…
+
+ );
+ }
+
+ return (
+
+
+
+
Equipped Gear
+
+
+
+
+
+
+
+ Inventory ({inventoryItems.length})
+
+
+
+
+
+ );
+}
+
+EquipmentTab.displayName = 'EquipmentTab';
diff --git a/src/components/game/tabs/EquipmentTab/EquipmentEffectsSummary.tsx b/src/components/game/tabs/EquipmentTab/EquipmentEffectsSummary.tsx
new file mode 100644
index 0000000..50af690
--- /dev/null
+++ b/src/components/game/tabs/EquipmentTab/EquipmentEffectsSummary.tsx
@@ -0,0 +1,93 @@
+'use client';
+
+import { computeEquipmentEffects } from '@/lib/game/effects';
+import type { EquipmentInstance } from '@/lib/game/types';
+
+interface EquipmentEffectsSummaryProps {
+ equipmentInstances: Record;
+ equippedInstances: Record;
+}
+
+const BONUS_LABELS: Record = {
+ maxMana: 'Max Mana',
+ regen: 'Mana Regen',
+ clickMana: 'Click Mana',
+ baseDamage: 'Base Damage',
+ elementCap: 'Element Cap',
+ critChance: 'Crit Chance',
+ attackSpeed: 'Attack Speed',
+ meditationEfficiency: 'Meditation Efficiency',
+ studySpeed: 'Study Speed',
+};
+
+const MULT_LABELS: Record = {
+ maxMana: 'Max Mana',
+ regen: 'Mana Regen',
+ clickMana: 'Click Mana',
+ baseDamage: 'Base Damage',
+ attackSpeed: 'Attack Speed',
+ elementCap: 'Element Cap',
+ meditationEfficiency: 'Meditation Efficiency',
+ studySpeed: 'Study Speed',
+};
+
+export function EquipmentEffectsSummary({ equipmentInstances, equippedInstances }: EquipmentEffectsSummaryProps) {
+ const { bonuses, multipliers, specials } = computeEquipmentEffects(equipmentInstances, equippedInstances);
+
+ const bonusEntries = Object.entries(bonuses).filter(([, v]) => v !== 0);
+ const multEntries = Object.entries(multipliers).filter(([, v]) => v !== 1);
+ const specialEntries = Array.from(specials);
+
+ if (bonusEntries.length === 0 && multEntries.length === 0 && specialEntries.length === 0) {
+ return null;
+ }
+
+ return (
+
+
Equipment Effects
+
+ {bonusEntries.length > 0 && (
+
+
Bonuses
+ {bonusEntries.map(([key, value]) => (
+
+
+ {BONUS_LABELS[key] || key}
+
+
+ {value > 0 ? '+' : ''}{typeof value === 'number' && !Number.isInteger(value) ? value.toFixed(2) : value}
+
+
+ ))}
+
+ )}
+
+ {multEntries.length > 0 && (
+
+
Multipliers
+ {multEntries.map(([key, value]) => (
+
+
+ {MULT_LABELS[key] || key}
+
+
+ ×{typeof value === 'number' ? value.toFixed(2) : value}
+
+
+ ))}
+
+ )}
+
+ {specialEntries.length > 0 && (
+
+
Specials
+ {specialEntries.map((id) => (
+
+ ★ {id}
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/src/components/game/tabs/EquipmentTab/EquipmentSlotGrid.tsx b/src/components/game/tabs/EquipmentTab/EquipmentSlotGrid.tsx
new file mode 100644
index 0000000..23da791
--- /dev/null
+++ b/src/components/game/tabs/EquipmentTab/EquipmentSlotGrid.tsx
@@ -0,0 +1,79 @@
+'use client';
+
+import { Package } from 'lucide-react';
+import type { EquipmentInstance, EquipmentSlot } from '@/lib/game/types';
+import { EQUIPMENT_TYPES, SLOT_NAMES } from '@/lib/game/data/equipment';
+import { RARITY_CSS_VAR } from '@/components/game/LootInventory/types';
+import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
+import { ActionButton } from '@/components/ui/action-button';
+
+interface EquipmentSlotGridProps {
+ equippedInstances: Record;
+ equipmentInstances: Record;
+ onUnequip: (slot: EquipmentSlot) => void;
+}
+
+const SLOTS: EquipmentSlot[] = ['mainHand', 'offHand', 'head', 'body', 'hands', 'feet', 'accessory1', 'accessory2'];
+
+export function EquipmentSlotGrid({ equippedInstances, equipmentInstances, onUnequip }: EquipmentSlotGridProps) {
+ return (
+
+ {SLOTS.map((slot) => {
+ const instanceId = equippedInstances[slot];
+ const instance = instanceId ? equipmentInstances[instanceId] : null;
+
+ if (instance) {
+ const type = EQUIPMENT_TYPES[instance.typeId];
+ const Icon = type ? CATEGORY_ICONS[type.category] || Package : Package;
+ const rarityColor = RARITY_CSS_VAR[instance.rarity] || 'var(--rarity-common)';
+
+ return (
+
+
+ {SLOT_NAMES[slot]}
+
+
+
+ {instance.name}
+
+
+ {type?.name || instance.typeId}
+
+
+ {instance.usedCapacity}/{instance.totalCapacity} cap
+
+
+ {instance.enchantments.length} enchant{instance.enchantments.length !== 1 ? 's' : ''} • {instance.quality}% quality
+
+
onUnequip(slot)}
+ >
+ Unequip
+
+
+ );
+ }
+
+ return (
+
+ );
+ })}
+
+ );
+}
diff --git a/src/components/game/tabs/EquipmentTab/InventoryList.tsx b/src/components/game/tabs/EquipmentTab/InventoryList.tsx
new file mode 100644
index 0000000..466de65
--- /dev/null
+++ b/src/components/game/tabs/EquipmentTab/InventoryList.tsx
@@ -0,0 +1,135 @@
+'use client';
+
+import { useState } from 'react';
+import { Package, Trash2 } from 'lucide-react';
+import type { EquipmentInstance, EquipmentSlot } from '@/lib/game/types';
+import { EQUIPMENT_TYPES, getValidSlotsForEquipmentType } from '@/lib/game/data/equipment';
+import { RARITY_CSS_VAR, RARITY_GLOW_CSS_VAR } from '@/components/game/LootInventory/types';
+import { CATEGORY_ICONS } from '@/components/game/LootInventory/icons';
+import { ActionButton } from '@/components/ui/action-button';
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from '@/components/ui/alert-dialog';
+
+interface InventoryListProps {
+ inventoryItems: [string, EquipmentInstance][];
+ equippedInstances: Record;
+ onEquip: (instanceId: string, slot: EquipmentSlot) => boolean;
+ onDelete: (instanceId: string) => void;
+}
+
+export function InventoryList({ inventoryItems, equippedInstances, onEquip, onDelete }: InventoryListProps) {
+ const [selectedSlot, setSelectedSlot] = useState>({});
+
+ if (inventoryItems.length === 0) {
+ return (
+
+ No items in inventory. Craft or find equipment to fill your slots.
+
+ );
+ }
+
+ return (
+
+ {inventoryItems.map(([instanceId, instance]) => {
+ const type = EQUIPMENT_TYPES[instance.typeId];
+ const Icon = type ? CATEGORY_ICONS[type.category] || Package : Package;
+ const rarityColor = RARITY_CSS_VAR[instance.rarity] || 'var(--rarity-common)';
+ const rarityGlow = RARITY_GLOW_CSS_VAR[instance.rarity] || 'var(--rarity-common-glow)';
+ const validSlots = type ? getValidSlotsForEquipmentType(type) : [];
+ const chosenSlot = selectedSlot[instanceId];
+ const availableSlots = validSlots.filter((s) => !equippedInstances[s]);
+
+ return (
+
+
+
+
+ {instance.name}
+
+
+ {type?.name || instance.typeId} • {instance.usedCapacity}/{instance.totalCapacity} cap
+
+
+ {instance.rarity} • {instance.enchantments.length} enchant{instance.enchantments.length !== 1 ? 's' : ''} • {instance.quality}% quality
+
+
+
+ {availableSlots.length > 1 ? (
+
+ ) : null}
+
{
+ const slot = availableSlots.length === 1 ? availableSlots[0] : chosenSlot;
+ if (slot) {
+ onEquip(instanceId, slot);
+ setSelectedSlot((prev) => {
+ const next = { ...prev };
+ delete next[instanceId];
+ return next;
+ });
+ }
+ }}
+ disabled={availableSlots.length === 0 || (availableSlots.length > 1 && !chosenSlot)}
+ >
+ Equip
+
+
+
+
+
+
+
+
+
+ Delete {instance.name}?
+
+ This action cannot be undone. The item will be permanently destroyed.
+
+
+
+ Cancel
+ onDelete(instanceId)}>
+ Delete
+
+
+
+
+
+
+ );
+ })}
+
+ );
+}
diff --git a/src/components/game/tabs/index.ts b/src/components/game/tabs/index.ts
index df5ce8b..65209ce 100644
--- a/src/components/game/tabs/index.ts
+++ b/src/components/game/tabs/index.ts
@@ -8,3 +8,4 @@ export { DebugTab } from './DebugTab';
export { AchievementsTab } from './AchievementsTab';
export { AttunementsTab } from './AttunementsTab';
export { PrestigeTab } from './PrestigeTab';
+export { EquipmentTab } from './EquipmentTab';