Dialogue and Skilling Panel System Documentation
Comprehensive guide for the unified skilling panels and NPC dialogue system (polished in PR #1093, March 26, 2026).Overview
PR #1093 introduced:- Unified Skilling Panels: Shared components and styling for all crafting/processing interfaces
- NPC Dialogue Redesign: Dedicated modal shell with live 3D VRM portraits
- Service Handoff Fix: Proper dialogue closure when opening bank/store/tanner
Skilling Panel System
Architecture
Before (duplicated styling):Shared Components
SkillingPanelBody
Container for skilling panel content with intro text and empty state.
- Intro text at top (optional)
- Empty state message when no children
- Consistent padding and spacing
- Responsive layout (mobile/desktop)
SkillingSection
Section container with consistent styling.
- Consistent padding (12px)
- Border radius (8px)
- Background color from theme
- Flexbox layout (column, gap: 8px)
SkillingQuantitySelector
Reusable quantity selector with preset buttons and custom input.
- Preset buttons: 1, 5, 10, All, X (custom)
- Custom input mode with validation
- Mobile-friendly touch targets (44px min)
- Keyboard support (Enter to submit, Escape to cancel)
- Auto-focus on custom input
Style Helpers
Migration Guide
Before (duplicated styling):Dialogue System
Architecture
Before (inline dialogue):DialoguePopupShell
Dedicated modal shell for NPC dialogue with focus management.- Focus Trap: Escape key closes dialogue
- ARIA Attributes:
role="dialog",aria-modal="true",aria-labelledby - Backdrop: Semi-transparent overlay with click-to-close
- Z-Index: Renders above game UI (z-index: 1000)
- Responsive: Mobile and desktop variants
DialogueCharacterPortrait
Live 3D VRM portrait rendering in dialogue panels.- Live Rendering: Real-time VRM character in dedicated viewport
- Camera Framing: Auto-frames character’s head/shoulders
- Lighting: Dedicated lighting setup for portrait quality
- Post-Processing: Bloom and tone mapping for visual polish
- Performance: Separate render loop (30 FPS) to avoid blocking game
Service Handoff Fix
Problem: Opening bank/store/tanner from dialogue left the dialogue panel open with a terminal “Continue” step. Fix: EmitDIALOGUE_CLOSE event when opening services.
Implementation:
Shared Components Reference
SkillingPanelBody
SkillingSection
SkillingQuantitySelector
Style Helpers
Integration Examples
Fletching Panel
Dialogue Panel with Portrait
Testing
Unit Tests
SkillingPanelShared.test.tsx:Integration Tests
dialogue-handoff.spec.ts:Troubleshooting
Issue: Skilling panel shows duplicate styling
Diagnosis: Check if panel is using shared components.Issue: Dialogue doesn’t close when opening bank
Diagnosis:DIALOGUE_CLOSEevent not emitted before service open- Dialogue panel not listening to
DIALOGUE_CLOSEevent - Service handoff code missing
Issue: Portrait canvas is blank
Diagnosis:- NPC entity not found
- VRM not loaded
- WebGPU renderer failed to initialize
- Canvas not mounted
Issue: Quantity selector doesn’t validate input
Diagnosis:- No validation on custom input
- Negative/zero quantities allowed
- Non-numeric input not rejected
Performance Considerations
Portrait Rendering
Optimization:- Separate render loop (30 FPS) to avoid blocking game (60 FPS)
- Dedicated WebGPU renderer (doesn’t share with main game renderer)
- VRM clone (doesn’t affect main game character)
- Dispose on unmount (prevents memory leaks)
Shared Component Memoization
Related Documentation
- SkillingPanelShared.tsx - Shared components
- DialoguePopupShell.tsx - Modal shell
- DialogueCharacterPortrait.tsx - Portrait renderer
- FletchingPanel.tsx - Example usage
- NPCInteractionHandler.ts - Service handoff
Changelog
March 26, 2026 (PR #1093)
- Extracted shared skilling panel components
- Unified layouts for all crafting/processing panels
- Added reusable quantity selector with presets
- Redesigned NPC dialogue with dedicated modal shell
- Added live 3D VRM portrait rendering
- Fixed service handoff (bank/store/tanner closes dialogue)
- Eliminated ~500 lines of duplicated styling
- 15 files changed, 1,623 additions, 1,265 deletions