5.3 KiB
5.3 KiB
UI Contracts: Bestiary Search & Stat Block Display
Branch: 021-bestiary-statblock | Date: 2026-03-06
Component Contracts
BestiarySearch
Purpose: Search input with autocomplete dropdown for creature selection.
Props:
onSelectCreature: (creature: Creature) => void— Called when user selects a creature from resultsonClose: () => void— Called when search is dismissed (Escape, click outside)
Behavior:
- Opens focused on the search input
- Filters creatures by case-insensitive substring match on name
- Minimum 2 characters before showing results
- Maximum 10 results shown at a time
- Keyboard navigation: ArrowUp/ArrowDown to navigate, Enter to select, Escape to close
- Shows "No creatures found" for zero-match queries
- Shows source tag next to creature name (e.g., "Goblin (MM 2024)")
StatBlock
Purpose: Renders a complete creature stat block.
Props:
creature: Creature— The creature data to display
Sections rendered (in order, omitted if data absent):
- Header: name, size, type, alignment
- Stats bar: AC, HP (average + formula), Speed
- Ability scores: STR/DEX/CON/INT/WIS/CHA with modifiers
- Properties: Saving Throws, Skills, Damage Vulnerabilities, Damage Resistances, Damage Immunities, Condition Immunities, Senses, Languages, CR + Proficiency Bonus
- Traits
- Spellcasting (rendered as a separate section after traits)
- Actions
- Bonus Actions
- Reactions
- Legendary Actions (with preamble text)
StatBlockPanel
Purpose: Responsive wrapper — side panel on desktop, drawer on mobile.
Props:
creature: Creature | null— Currently displayed creature (null = closed)onClose: () => void— Close the panel/drawer
Behavior:
- Desktop (>= 1024px): Renders as a right-side panel, tracker shifts left
- Mobile (< 1024px): Renders as a slide-over drawer from right with backdrop
- Close button always visible
- Panel scrolls independently of the main content
ActionBar (modified)
Extended Props:
onAddCombatant: (name: string) => void— Existing: add plain combatantonAddFromBestiary: (creature: Creature) => void— New: add creature with stat pre-fillsuggestions: Creature[]— Matching creatures for current name inputonSearchChange: (query: string) => void— Notify parent of input changes for suggestion filtering
New Elements:
- Magnifying glass icon button next to input → opens dedicated BestiarySearch
- Autocomplete suggestion list below input when typing (>= 2 chars and matches exist)
Hook Contracts
useBestiary
Purpose: Provides creature search and lookup from the bundled bestiary.
Returns:
search: (query: string) => Creature[]— Filter creatures by name substringgetCreature: (id: CreatureId) => Creature | undefined— Look up creature by IDallCreatures: Creature[]— Full list (for potential future use)
Behavior:
- Loads and normalizes bestiary data once on initialization (lazy, memoized)
- Search is synchronous (in-memory filter)
- Returns results sorted alphabetically by name
useEncounter (extended)
Extended return:
addFromBestiary: (creature: Creature) => void— New: adds combatant with auto-numbered name, pre-filled HP/AC, and creatureId link
Auto-numbering behavior:
- Checks existing combatant names for conflicts with the creature's base name
- If no conflict: uses creature name as-is
- If one existing match: renames existing to "Name 1", new one becomes "Name 2"
- If N existing matches: new one becomes "Name N+1"
- Names remain editable after auto-numbering
Layout Contract
App (modified)
Desktop layout (>= 1024px, stat block open):
+--------------------------------------------------+
| Header |
+-------------------------+------------------------+
| Tracker (flex-1) | Stat Block (~400px) |
| - Turn Navigation | - Scrollable |
| - Combatant List | - Close button |
| - Action Bar | |
+-------------------------+------------------------+
Desktop layout (stat block closed):
+--------------------------------------------------+
| Header |
| Tracker (max-w-2xl, centered) |
| - Turn Navigation |
| - Combatant List |
| - Action Bar |
+--------------------------------------------------+
Mobile layout (< 1024px, stat block open):
+--------------------------------------------------+
| Header |
| Tracker (full width) |
| - Turn Navigation |
| - Combatant List |
| - Action Bar |
| |
| +----------------------------------------------+ |
| | Drawer (slide from right, 85% width) | |
| | - Close button | |
| | - Stat Block (scrollable) | |
| +----------------------------------------------+ |
| | Backdrop (click to close) | |
+--------------------------------------------------+