# Research: Bottom Bar Overhaul ## R-001: Batch Add via Existing Domain API **Decision**: Call `addFromBestiary(result)` in a loop N times (once per queued count) rather than creating a new batch domain function. **Rationale**: The existing `addFromBestiary` in `use-encounter.ts` already handles name auto-numbering (via `resolveCreatureName`), HP/AC assignment, and creatureId derivation. Calling it N times is correct because each call resolves the creature name against the updated combatant list, producing proper sequential numbering (e.g., "Goblin 1", "Goblin 2", "Goblin 3"). **Alternatives considered**: - New domain-level `addBatchCombatants` function: Rejected because auto-numbering depends on seeing previously-added names, which the loop approach already handles. A batch function would duplicate logic. - Application-layer batch use case: Rejected — no persistence coordination needed; the hook already manages state. ## R-002: Custom Creature Optional Fields (Initiative, AC, Max HP) **Decision**: Extend the existing `onAddCombatant` callback (or create a sibling) to accept optional `{ initiative?: number; ac?: number; maxHp?: number }` alongside the name. The `use-encounter` hook's `addCombatant` flow will be extended to apply these fields to the newly created combatant. **Rationale**: The domain `Combatant` type already has `initiative?`, `ac?`, and `maxHp?` fields. The domain `addCombatant` function creates a combatant with just `id` and `name`; the hook currently patches `currentHp`/`maxHp`/`ac` after creation for bestiary creatures. The same pattern works for custom creatures. **Alternatives considered**: - Extend domain `addCombatant` to accept optional fields: Rejected — the domain function is minimal by design (pure add with name validation). Post-creation patching is the established pattern. - New domain function `addCustomCombatant`: Rejected — unnecessary complexity for fields that are just optional patches on the existing type. ## R-003: Stat Block Preview from Dropdown **Decision**: Pass a `onViewStatBlock(result: SearchResult)` callback from App.tsx through ActionBar. When triggered, it derives the `CreatureId` from the search result (same `${source}:${slug}` pattern used in `addFromBestiary`) and opens the stat block panel for that creature. **Rationale**: The stat block panel infrastructure already exists and accepts a `CreatureId`. The only new wiring is a callback from the dropdown row to the panel opener. **Alternatives considered**: - Inline stat block preview in the dropdown: Rejected — the dropdown is compact and the stat block panel already handles full rendering, source fetching, and caching. ## R-004: Unified Search Flow vs Separate BestiarySearch Component **Decision**: Merge the separate `BestiarySearch` component's functionality into the action bar's existing inline search. Remove the toggle between "form mode" and "search mode" (`searchOpen` state). The action bar always shows a single input field that serves both purposes. **Rationale**: The current action bar has two modes — a name input with inline suggestions, and a separate full `BestiarySearch` overlay toggled by the search button. The spec calls for a unified flow where the single input field shows bestiary results as you type (already working via `suggestions`), with click-to-queue behavior replacing the immediate add-on-click. The separate `BestiarySearch` component becomes redundant. **Alternatives considered**: - Keep both modes: Rejected — the spec explicitly merges the flows (dropdown opens on type, search button becomes stat block viewer). ## R-005: Queue State Management **Decision**: Queue state is local React state in the action bar component: `{ result: SearchResult; count: number } | null`. No hook or context needed. **Rationale**: The queue is purely ephemeral and scoped to the action bar's interaction lifecycle. It resets on confirm, escape, or when the queued creature leaves the search results. **Alternatives considered**: - Custom hook for queue state: Rejected — the state is simple (one nullable object) and doesn't need to be shared.