From 43780772f6d892d0312495c88056d3fbb589c9ca Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 17 Mar 2026 12:48:38 +0100 Subject: [PATCH] Improve bestiary icon UX and auto-update stat block on turn change - Use Book/BookOpen icons to indicate stat block open state - Bump combatant icons (bestiary + PC) from 14px to 16px - Use text-foreground for bestiary icon visibility - Auto-update stat block panel to active combatant's creature on turn advance - Update bestiary spec edge case to reflect new behavior Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/web/src/App.tsx | 12 ++++++++++++ apps/web/src/components/combatant-row.tsx | 10 ++++++---- specs/004-bestiary/spec.md | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index ef5c039..cb4927c 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -203,6 +203,15 @@ export function App() { const playerCharacterRef = useRef(null); const actionBarAnim = useActionBarAnimation(encounter.combatants.length); + // Auto-update stat block panel when the active combatant changes + const activeCreatureId = + encounter.combatants[encounter.activeIndex]?.creatureId; + useEffect(() => { + if (activeCreatureId && sidePanel.panelView.mode === "creature") { + sidePanel.showCreature(activeCreatureId); + } + }, [activeCreatureId, sidePanel.panelView.mode, sidePanel.showCreature]); + // Auto-scroll to the active combatant when the turn changes const activeRowRef = useRef(null); useEffect(() => { @@ -282,6 +291,9 @@ export function App() { ? () => handleCombatantStatBlock(c.creatureId as string) : undefined } + isStatBlockOpen={ + c.creatureId === sidePanel.selectedCreatureId + } onRollInitiative={ c.creatureId ? handleRollInitiative : undefined } diff --git a/apps/web/src/components/combatant-row.tsx b/apps/web/src/components/combatant-row.tsx index 6b0bda7..7ea7ef6 100644 --- a/apps/web/src/components/combatant-row.tsx +++ b/apps/web/src/components/combatant-row.tsx @@ -4,7 +4,7 @@ import { deriveHpStatus, type PlayerIcon, } from "@initiative/domain"; -import { BookOpen, Brain, X } from "lucide-react"; +import { Book, BookOpen, Brain, X } from "lucide-react"; import { type Ref, useCallback, useEffect, useRef, useState } from "react"; import { cn } from "../lib/utils"; import { AcShield } from "./ac-shield"; @@ -41,6 +41,7 @@ interface CombatantRowProps { onToggleCondition: (id: CombatantId, conditionId: ConditionId) => void; onToggleConcentration: (id: CombatantId) => void; onShowStatBlock?: () => void; + isStatBlockOpen?: boolean; onRollInitiative?: (id: CombatantId) => void; } @@ -396,6 +397,7 @@ export function CombatantRow({ onToggleCondition, onToggleConcentration, onShowStatBlock, + isStatBlockOpen, onRollInitiative, }: CombatantRowProps & { ref?: Ref }) { const { id, name, initiative, maxHp, currentHp } = combatant; @@ -480,9 +482,9 @@ export function CombatantRow({ onClick={onShowStatBlock} title="View stat block" aria-label="View stat block" - className="shrink-0 text-muted-foreground transition-colors hover:text-hover-neutral" + className="shrink-0 text-foreground transition-colors hover:text-hover-neutral" > - + {isStatBlockOpen ? : } )} {!!combatant.icon && @@ -495,7 +497,7 @@ export function CombatantRow({ ]; return PcIcon ? ( diff --git a/specs/004-bestiary/spec.md b/specs/004-bestiary/spec.md index 000bc99..50927cb 100644 --- a/specs/004-bestiary/spec.md +++ b/specs/004-bestiary/spec.md @@ -264,7 +264,7 @@ As a DM with a creature pinned, I want to collapse the right (browse) panel inde ### Edge Cases - User pins a creature and then that creature is removed from the encounter: the pinned panel continues displaying the creature's stat block (data is already loaded). -- Active combatant changes while panel is open or collapsed: advancing turns does not auto-show or update the stat block panel. The panel only changes when the user explicitly clicks a book icon. If the panel is collapsed, it stays collapsed. +- Active combatant changes while panel is open: if the new active combatant has a creature, the panel auto-updates to show that creature's stat block. If the new active combatant has no creature, the panel remains on the previous creature. If the panel is collapsed, it stays collapsed. If the panel is closed, it stays closed. - Viewport resized from wide to narrow while a creature is pinned: the pinned (left) panel is hidden and the pin button disappears; resizing back to wide restores the pinned panel. - User is in bulk import mode and tries to collapse: the collapse/expand behavior applies to the bulk import panel identically. - Panel showing a source fetch prompt: the pin button is hidden.