Implement the 021-bestiary-statblock feature that adds a searchable D&D 2024 Monster Manual creature library with inline autocomplete suggestions, full stat block display in a fixed side panel, auto-numbering of duplicate creature names, HP/AC pre-fill from bestiary data, and automatic stat block display on turn change for wide viewports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-09 11:01:07 +01:00
parent 04a4f18f98
commit fa078be2f9
30 changed files with 66221 additions and 56 deletions

View File

@@ -3,7 +3,7 @@ import {
type ConditionId,
deriveHpStatus,
} from "@initiative/domain";
import { Brain, Shield, X } from "lucide-react";
import { BookOpen, Brain, Shield, X } from "lucide-react";
import { useCallback, useEffect, useRef, useState } from "react";
import { cn } from "../lib/utils";
import { ConditionPicker } from "./condition-picker";
@@ -34,6 +34,7 @@ interface CombatantRowProps {
onSetAc: (id: CombatantId, value: number | undefined) => void;
onToggleCondition: (id: CombatantId, conditionId: ConditionId) => void;
onToggleConcentration: (id: CombatantId) => void;
onShowStatBlock?: () => void;
}
function EditableName({
@@ -276,6 +277,7 @@ export function CombatantRow({
onSetAc,
onToggleCondition,
onToggleConcentration,
onShowStatBlock,
}: CombatantRowProps) {
const { id, name, initiative, maxHp, currentHp } = combatant;
const status = deriveHpStatus(currentHp, maxHp);
@@ -364,8 +366,19 @@ export function CombatantRow({
/>
{/* Name */}
<div className={cn(dimmed && "opacity-50")}>
<div className={cn("flex items-center gap-1", dimmed && "opacity-50")}>
<EditableName name={name} combatantId={id} onRename={onRename} />
{onShowStatBlock && (
<button
type="button"
onClick={onShowStatBlock}
className="text-muted-foreground hover:text-amber-400 transition-colors"
title="View stat block"
aria-label="View stat block"
>
<BookOpen size={14} />
</button>
)}
</div>
{/* AC */}