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
code
┌───────────────────────────────────────────────────┐ │ TURN INDICATOR │ PHASE PIPELINE │ MODIFIERS │ ← PhaseHeader ├──────────────────┴───────┬───────────┴────────────┤ │ │ │ │ PLAYER PANEL │ ENEMY PANEL │ ← ConfrontationZone │ (CharacterPanel) │ (CharacterPanel) │ │ │ │ ├──────────────────────────┴────────────────────────┤ │ QUICK ACTIONS (SIDE/TOGGLE) │ MAIN ACTIONS │ ← ActionDock └───────────────────────────────┴───────────────────┘
Component Hierarchy
code
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
code
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:
typescript
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)
bash
# 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
typescript
// 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)
typescript
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
typescript
// 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.tsxwith 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
VSDividerwith 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 |