# Research: Combatant Row UI Polish **Feature**: 027-ui-polish | **Date**: 2026-03-10 ## R1: CSS Shield Shape for AC **Decision**: Use an inline SVG background with the AC number centered inside, rendered as a dedicated `AcShield` component. **Rationale**: CSS `clip-path` clips the element itself (including borders and backgrounds) but makes it hard to get a clean outlined shield. An inline SVG shield path with the number as a `` or overlaid HTML gives full control over stroke, fill, and sizing. This matches how D&D Beyond and character sheet PDFs render AC. **Alternatives considered**: - `clip-path: polygon(...)` — clips the element shape but can't produce a stroke outline easily. Would need a pseudo-element hack. - Background image SVG — works but harder to make the stroke color respond to CSS custom properties (theme-aware). - Lucide Shield icon with number overlaid via absolute positioning — fragile alignment, icon stroke competes with the number visually. **Approach**: Create a small SVG shield outline (viewBox-based) as a React component. The AC number is rendered as a centered `` overlaid on the SVG using relative/absolute positioning. The SVG uses `currentColor` for the stroke so it inherits theme colors. Size: approximately 28×32px to comfortably fit 1-3 digit numbers. ## R2: Row Click Stat Block — Event Delegation **Decision**: Attach `onClick` handler to the row container, use `event.stopPropagation()` on all interactive child elements to prevent bubbling. **Rationale**: This is the standard pattern for "click anywhere except interactive elements." Each interactive element (initiative, HP, AC, conditions, "+", "×", concentration) already has its own click handler — adding `stopPropagation()` to each ensures the row-level handler only fires for non-interactive areas. **Alternatives considered**: - Checking `event.target` against a list of interactive selectors — fragile and hard to maintain. - Wrapping non-interactive areas in a separate clickable element — would complicate the grid layout. ## R3: Hover-Only Elements — Touch Device Accessibility **Decision**: Use CSS `opacity-0 group-hover:opacity-100` for hide/show, combined with `focus-within:opacity-100` for keyboard accessibility. On touch devices, the elements are accessible via tap (the first tap reveals, second tap activates — standard mobile pattern with opacity transitions). **Rationale**: The concentration button already uses this exact pattern (`opacity-0 group-hover:opacity-50`). Extending it to the remove button and "+" condition button is consistent. **Alternatives considered**: - `display: none` / `display: block` — causes layout shifts (violates FR-004). - `visibility: hidden` / `visible` — works but doesn't allow opacity transitions. ## R4: Inline Conditions Layout **Decision**: Move `ConditionTags` and the "+" button into the name column's flex container (the `1fr` column), after the name text. The conditions and "+" sit inline with the name, wrapping if needed. **Rationale**: The name column is already a flex container (`flex items-center gap-1`). Adding condition icons here is natural. The `truncate` class on the name will need adjustment — the name should shrink (`min-w-0 truncate` on just the name text) while conditions fill remaining space. **Alternatives considered**: - Dedicated column for conditions — adds complexity to the grid and uses horizontal space poorly. - Conditions as a second flex row within the name cell — still uses `flex-wrap` but explicitly creates a two-row layout when many conditions exist. ## R5: D20 Icon Sizing **Decision**: Increase from `h-5 w-5` (20px) to `h-7 w-7` (28px). The initiative column is 3rem (48px) wide, so 28px fits comfortably with padding. **Rationale**: At 20px the internal geometry lines of the d20 are too dense to read as a die shape. At 28px the icosahedron silhouette becomes recognizable. The column has room — the d20 button is already `h-7 w-full` so only the icon within needs to grow. **Alternatives considered**: - `h-6 w-6` (24px) — marginal improvement, still a bit small. - `h-8 w-8` (32px) — might feel oversized relative to the initiative numbers in adjacent rows. ## R6: Concentration Click Target **Decision**: Expand the concentration button from `1.25rem` width to fill the full gutter. Change the grid column from `1.25rem` to `2rem` (or use padding on the button to extend its hit area to the row edge). The brain icon stays centered visually. **Rationale**: The left border of the row already has `px-3` padding. The concentration column at `1.25rem` (20px) with a 16px icon leaves very little extra hit area. Widening the column or extending the button's padding makes tapping much easier. **Alternatives considered**: - Negative margin on the button — hacky, could affect layout. - Separate invisible overlay — unnecessary complexity.