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) <noreply@anthropic.com>
This commit is contained in:
@@ -203,6 +203,15 @@ export function App() {
|
|||||||
const playerCharacterRef = useRef<PlayerCharacterSectionHandle>(null);
|
const playerCharacterRef = useRef<PlayerCharacterSectionHandle>(null);
|
||||||
const actionBarAnim = useActionBarAnimation(encounter.combatants.length);
|
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
|
// Auto-scroll to the active combatant when the turn changes
|
||||||
const activeRowRef = useRef<HTMLDivElement>(null);
|
const activeRowRef = useRef<HTMLDivElement>(null);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -282,6 +291,9 @@ export function App() {
|
|||||||
? () => handleCombatantStatBlock(c.creatureId as string)
|
? () => handleCombatantStatBlock(c.creatureId as string)
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
isStatBlockOpen={
|
||||||
|
c.creatureId === sidePanel.selectedCreatureId
|
||||||
|
}
|
||||||
onRollInitiative={
|
onRollInitiative={
|
||||||
c.creatureId ? handleRollInitiative : undefined
|
c.creatureId ? handleRollInitiative : undefined
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
deriveHpStatus,
|
deriveHpStatus,
|
||||||
type PlayerIcon,
|
type PlayerIcon,
|
||||||
} from "@initiative/domain";
|
} 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 { type Ref, useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { cn } from "../lib/utils";
|
import { cn } from "../lib/utils";
|
||||||
import { AcShield } from "./ac-shield";
|
import { AcShield } from "./ac-shield";
|
||||||
@@ -41,6 +41,7 @@ interface CombatantRowProps {
|
|||||||
onToggleCondition: (id: CombatantId, conditionId: ConditionId) => void;
|
onToggleCondition: (id: CombatantId, conditionId: ConditionId) => void;
|
||||||
onToggleConcentration: (id: CombatantId) => void;
|
onToggleConcentration: (id: CombatantId) => void;
|
||||||
onShowStatBlock?: () => void;
|
onShowStatBlock?: () => void;
|
||||||
|
isStatBlockOpen?: boolean;
|
||||||
onRollInitiative?: (id: CombatantId) => void;
|
onRollInitiative?: (id: CombatantId) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,6 +397,7 @@ export function CombatantRow({
|
|||||||
onToggleCondition,
|
onToggleCondition,
|
||||||
onToggleConcentration,
|
onToggleConcentration,
|
||||||
onShowStatBlock,
|
onShowStatBlock,
|
||||||
|
isStatBlockOpen,
|
||||||
onRollInitiative,
|
onRollInitiative,
|
||||||
}: CombatantRowProps & { ref?: Ref<HTMLDivElement> }) {
|
}: CombatantRowProps & { ref?: Ref<HTMLDivElement> }) {
|
||||||
const { id, name, initiative, maxHp, currentHp } = combatant;
|
const { id, name, initiative, maxHp, currentHp } = combatant;
|
||||||
@@ -480,9 +482,9 @@ export function CombatantRow({
|
|||||||
onClick={onShowStatBlock}
|
onClick={onShowStatBlock}
|
||||||
title="View stat block"
|
title="View stat block"
|
||||||
aria-label="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"
|
||||||
>
|
>
|
||||||
<BookOpen size={14} />
|
{isStatBlockOpen ? <BookOpen size={16} /> : <Book size={16} />}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{!!combatant.icon &&
|
{!!combatant.icon &&
|
||||||
@@ -495,7 +497,7 @@ export function CombatantRow({
|
|||||||
];
|
];
|
||||||
return PcIcon ? (
|
return PcIcon ? (
|
||||||
<PcIcon
|
<PcIcon
|
||||||
size={14}
|
size={16}
|
||||||
style={{ color: iconColor }}
|
style={{ color: iconColor }}
|
||||||
className="shrink-0"
|
className="shrink-0"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ As a DM with a creature pinned, I want to collapse the right (browse) panel inde
|
|||||||
### Edge Cases
|
### 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).
|
- 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.
|
- 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.
|
- 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.
|
- Panel showing a source fetch prompt: the pin button is hidden.
|
||||||
|
|||||||
Reference in New Issue
Block a user