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:
140
specs/021-bestiary-statblock/contracts/ui-contracts.md
Normal file
140
specs/021-bestiary-statblock/contracts/ui-contracts.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# 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 results
|
||||
- `onClose: () => 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):
|
||||
1. Header: name, size, type, alignment
|
||||
2. Stats bar: AC, HP (average + formula), Speed
|
||||
3. Ability scores: STR/DEX/CON/INT/WIS/CHA with modifiers
|
||||
4. Properties: Saving Throws, Skills, Damage Vulnerabilities, Damage Resistances, Damage Immunities, Condition Immunities, Senses, Languages, CR + Proficiency Bonus
|
||||
5. Traits
|
||||
6. Spellcasting (rendered as a separate section after traits)
|
||||
7. Actions
|
||||
8. Bonus Actions
|
||||
9. Reactions
|
||||
10. 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 combatant
|
||||
- `onAddFromBestiary: (creature: Creature) => void` — New: add creature with stat pre-fill
|
||||
- `suggestions: Creature[]` — Matching creatures for current name input
|
||||
- `onSearchChange: (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 substring
|
||||
- `getCreature: (id: CreatureId) => Creature | undefined` — Look up creature by ID
|
||||
- `allCreatures: 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) | |
|
||||
+--------------------------------------------------+
|
||||
```
|
||||
Reference in New Issue
Block a user