Combat UI Pattern A - Split-Panel Implementation
This skill guides implementation of the Split-Panel Combat UI, transforming the vertical theater mode into a horizontal confrontation layout.
Architecture Overview
┌───────────────────────────────────────────────────┐ │ TURN INDICATOR │ PHASE PIPELINE │ MODIFIERS │ ← PhaseHeader ├──────────────────┴───────┬───────────┴────────────┤ │ │ │ │ PLAYER PANEL │ ENEMY PANEL │ ← ConfrontationZone │ (CharacterPanel) │ (CharacterPanel) │ │ │ │ ├──────────────────────────┴────────────────────────┤ │ QUICK ACTIONS (SIDE/TOGGLE) │ MAIN ACTIONS │ ← ActionDock └───────────────────────────────┴───────────────────┘
Component Hierarchy
Combat.tsx (scene orchestrator) ├── CombatLayout.tsx (CSS Grid container) │ ├── PhaseHeader.tsx (top status bar) │ │ ├── TurnIndicator │ │ ├── PhasePipeline │ │ ├── SideActionCounter │ │ └── ApproachModifier │ │ │ ├── ConfrontationZone.tsx (battle area) │ │ ├── CharacterPanel.tsx (player variant) │ │ │ ├── CharacterSprite │ │ │ ├── IdentityBar │ │ │ ├── ResourceBars (HP/CP) │ │ │ └── BuffBar │ │ │ │ │ ├── VSDivider.tsx (center emblem) │ │ │ │ │ └── CharacterPanel.tsx (enemy variant) │ │ ├── CharacterSprite │ │ ├── IdentityBar (name, tier, element) │ │ ├── HealthBar │ │ ├── DefenseStats │ │ └── BuffBar │ │ │ └── ActionDock.tsx (skill bar) │ ├── QuickActionsSection │ │ ├── QuickActionCard (SIDE skills) │ │ └── QuickActionCard (TOGGLE skills) │ ├── MainActionsSection │ │ └── MainActionCard (MAIN skills) │ └── ControlButtons (Auto, End Turn) │ └── FloatingTextLayer (z-50, unchanged)
File Structure
src/components/combat/ ├── index.ts # Barrel exports ├── CombatLayout.tsx # Grid container ├── PhaseHeader.tsx # Top status bar ├── ConfrontationZone.tsx # Player vs Enemy area ├── CharacterPanel.tsx # Reusable character display ├── VSDivider.tsx # Center VS emblem ├── ActionDock.tsx # Bottom skill bar ├── QuickActionCard.tsx # Compact SIDE/TOGGLE card └── MainActionCard.tsx # Large MAIN skill card
Implementation Workflow
Step 1: Identify Target Component
Ask user which component to implement:
-
CombatLayout - Start here for new implementation
-
PhaseHeader - Top status bar
-
ConfrontationZone - Battle area with both panels
-
CharacterPanel - Individual character display
-
VSDivider - Center emblem and effects
-
ActionDock - Bottom skill bar
-
QuickActionCard - Compact skill card variant
-
MainActionCard - Large skill card variant
Step 2: Load Component Reference
Based on selection, load the appropriate reference:
-
Layout/Structure: See layout-specs.md
-
Component Props: See component-interfaces.md
-
Styling Guide: See styling-tokens.md
-
Animation Specs: See animations.md
Step 3: Generate Component Code
Follow the component template pattern:
import React from 'react'; import { cn } from '@/lib/utils'; // if using cn utility
interface ComponentNameProps { // Props from component-interfaces.md }
export const ComponentName: React.FC<ComponentNameProps> = ({ // destructured props }) => { return ( <div className={cn( // Base styles from styling-tokens.md // Conditional styles )}> {/* Component content */} </div> ); };
Step 4: Wire to Combat.tsx
After component creation:
-
Export from components/combat/index.ts
-
Import in Combat.tsx
-
Replace corresponding section
-
Pass required props from existing state
Quick Implementation Commands
Create All Files (Scaffolding)
Create directory
mkdir -p src/components/combat
Create all component files
touch src/components/combat/{index,CombatLayout,PhaseHeader,ConfrontationZone,CharacterPanel,VSDivider,ActionDock,QuickActionCard,MainActionCard}.tsx
Barrel Export Template
// src/components/combat/index.ts export { CombatLayout } from './CombatLayout'; export { PhaseHeader } from './PhaseHeader'; export { ConfrontationZone } from './ConfrontationZone'; export { CharacterPanel } from './CharacterPanel'; export { VSDivider } from './VSDivider'; export { ActionDock } from './ActionDock'; export { QuickActionCard } from './QuickActionCard'; export { MainActionCard } from './MainActionCard';
Props Mapping from Existing Code
From App.tsx → Combat.tsx (unchanged)
player: Player enemy: Enemy turnState: 'PLAYER' | 'ENEMY_TURN' turnPhase: TurnPhaseState combatState: CombatState onUseSkill: (skill: Skill) => void onPassTurn: () => void onToggleAutoCombat: () => void autoCombatEnabled: boolean
Combat.tsx → New Components
// PhaseHeader turnState, turnPhase, combatState.approach
// ConfrontationZone player, enemy, playerStats, enemyStats
// CharacterPanel (player) character: player, stats: playerStats, variant: 'player'
// CharacterPanel (enemy) character: enemy, stats: enemyStats, variant: 'enemy'
// ActionDock skills: player.skills, turnPhase, onUseSkill, onPassTurn
Migration Strategy
Phase 1: Layout Foundation
-
Create CombatLayout.tsx with CSS Grid
-
Create placeholder components
-
Add feature flag in Combat.tsx
Phase 2: Component Extraction
-
Implement CharacterPanel (extract from PlayerHUD + CinematicViewscreen)
-
Implement ActionDock (extract from skill grids)
-
Implement PhaseHeader (extract from inline indicators)
Phase 3: Visual Polish
-
Add VSDivider with effects
-
Implement animations
-
Adjust floating text positions
Phase 4: Cleanup
-
Remove old theater mode code
-
Remove feature flag
-
Update tests
Reference Files
-
layout-specs.md - CSS Grid structure, responsive breakpoints
-
component-interfaces.md - TypeScript interfaces for all components
-
styling-tokens.md - Colors, spacing, typography tokens
-
animations.md - Animation keyframes and transitions
Output Format
Generate TypeScript React components with:
-
TypeScript interface for props
-
Tailwind CSS for styling (matching existing codebase)
-
Responsive classes (mobile fallback to vertical)
-
Memoization where appropriate (React.memo for cards)
-
Accessibility attributes (aria-labels, roles)
Existing Code References
When implementing, reference these existing files:
New Component Reference From
CharacterPanel (player) src/components/PlayerHUD.tsx
CharacterPanel (enemy) src/scenes/Combat.tsx lines 113-305
ActionDock src/scenes/Combat.tsx lines 308-607
QuickActionCard src/components/SkillCard.tsx
MainActionCard src/components/SkillCard.tsx
PhaseHeader src/scenes/Combat.tsx lines 311-328