Skip to content

UI structure

Overview

The app uses a React + PixiJS hybrid: React renders screens (Menu, New Game, Settings) and the game layout shell; PixiJS renders the isometric map inside a canvas. Entry point: src/client/react/main.tsxApp.tsxinit() from main.ts. When useReactLayout: true (default), the game screen shows only the map in Pixi; sidebar and footer are React components. GameBridge (GameUIApi) exposes IsometricMap API to React; StorageDriver abstracts localStorage/sessionStorage for persistence.

Screens

Screen Path Description
Menu react/screens/MenuScreen.tsx Main menu, New Game, Settings
New Game react/screens/NewGameScreen.tsx Configure map, start game
Loading react/screens/LoadingScreen.tsx Loading progress (React)
Singleplayer Pixi + GameFooter + GameOverlays Map full width, footer + overlays
Settings react/screens/SettingsScreen.tsx Tabs: Game, Graphics, Audio
Coming Soon react/screens/ComingSoonScreen.tsx Placeholder for multiplayer
  • NavigationManager – uses window.location.hash (#menu, #singleplayer, #settings/graphics)
  • ScreenStateManager – persists last screen in localStorage
  • NavigationManager.onNavigate(screen, callback) – register listeners per screen
  • NavigationManager.navigateTo(screen, pushToHistory, tab) – navigate

Game screen layout

Legacy (sidebar): Sidebar left ⅕, GameArea center, Footer bottom.

React layout (default): Sidebar removed; map full width; footer fixed at bottom; overlays float above map.

┌─────────────────────────────────────────────────────────┐
│  GameArea (map, full width)          │ Menu │ FPS │ Mini │
│                                      │Speed │ Dev │ map  │
│  Overlays: Menu, Speed, Dev, FPS,    ├──────┴─────┴──────┤
│  Minimap, SelectionPanel (draggable) │ SelectionPanel   │
├──────────────────────────────────────┴───────────────────┤
│  Footer (fixed height ~220px)                           │
│  Tabs: Order manager | Colonists | Jobs                 │
└─────────────────────────────────────────────────────────┘

GameArea

  • Wraps IsometricMap (map, camera, zones, objects, jobs)
  • Handles map click → object selection, area selection
  • Passes selection to sidebar via handleObjectSelection(objectData, panelType)
  • Shows TileSelectorModal for tile-based actions
  • Right-click (PPM) on map: context menu (object actions e.g. Chop/Mine, or "Move here" / "Run here" when colonist is selected). Orders from this menu are assigned to the selected colonist.
  • selectedColonistId – set when colonist is selected (from map click or footer list); required for right-click "Move here" / "Run here". In React layout, GameOverlays.onSelectionChange calls setSelectedColonistId for type: 'citizen', and clears it when selection changes or panel closes.
  • Position: Left, ⅕ of screen width
  • Content: Menu button, Minimap, SpeedControls, single panel slot
  • Panels (one visible at a time):
Panel Type Shows when
InfoPanel citizen Colonist selected
WorkshopPanel workshop Workshop/structure selected
ObjectPanel object Tree, stone, resource selected
ZonePanel zone Zone selected (also as overlay)
AreaSelectionPanel area-selection Area selection mode active
  • Zone overlay – ZonePanel content drawn above sidebar when a zone is selected
  • Dev panel – Tile selector, place colonist (toggle via DEV button)
  • Position: Bottom, ~18% of height
  • Tabs: Order manager, Colonists, Jobs
  • Order manager – CategoriesPanel (¼) + OrdersGrid (¾) for placing orders
  • Colonists – ColonistsPanel (list of colonists)
  • Jobs – JobsPanel (pending jobs)

Panels

Panel Purpose
InfoPanel Colonist: name, skills, needs, job preferences, body parts
WorkshopPanel Structure: production, recipes
ObjectPanel Object: name, actions (chop, mine)
ZonePanel Zone: type, remove, storage summary
AreaSelectionPanel Area selection: confirm/cancel, bounds
CategoriesPanel Order categories (Orders, Structures, etc.)
OrdersGrid Order buttons (Chop, Mine, etc.)
ColonistsPanel Colonist list, select → InfoPanel
JobsPanel Pending jobs list
Minimap Small map overview, click to move camera
SpeedControls 1x, 2x, 3x game speed

Generic components

In components/generic/:

  • Panel – rounded rect background
  • Button, Checkbox, Toggle, Slider, Dropdown
  • Tooltip – hover tooltip
  • ProgressBar, Separator
  • Modal – overlay modal
  • TabButton – tab-style button
  • FPSCounter – fps display

React layout (useReactLayout)

When useReactLayout is true (default):

  • Sidebar removed – map occupies full width; Pixi GameArea has sidebarWidth: 0
  • Footer – React GameFooter at bottom (Order manager, Colonists, Jobs tabs)
  • Overlays – React GameOverlays renders draggable panels above the map (pointer-events: none on wrapper, panels use auto where needed)
  • GameBridgeonGameReady(api) passes GameUIApi to React; selection events via onSelectionChange, map actions via executeAction, setColonistJobAllowed, etc.
  • Canvas reparenting – on Singleplayer, canvas moves into centerRef; on other screens, into fullscreenRef

Overlays (DraggableOverlayPanel)

Overlay storageKey Resizable Purpose
MenuOverlay (fixed) no Menu button (top-left)
MinimapOverlay simu-game-minimap yes Map thumbnail, click-to-jump; resize handle
FpsOverlay simu-game-fps no FPS counter
ZoomOverlay simu-game-zoom no Zoom ± buttons
SpeedOverlay simu-game-speed no 1x, 2x, 3x speed
DevOverlay simu-game-dev no Tile selector, Place colonist, Clear tile, etc.
SelectionPanelOverlay simu-game-selection-panel yes Colonist/Zone/Object/Area panel (draggable, closable)
  • Position/size/collapsed persisted via StorageDriver (sessionStorage by default)
  • DraggableOverlayPanel – header with label, drag handle, collapse (−/▶), optional close (X), optional resize handle

Minimap

  • Sidebar mode: Inside sidebar, below menu button
  • Overlay mode (React layout): Top-right of canvas; header with collapse/drag; position + collapsed state persisted in sessionStorage
  • Implementation: getBounds() + proportional position; hitArea blocks map clicks
  • See minimap.md for full technical details

Z-index (GameScreen)

  • GameArea: 1
  • Sidebar: 100
  • Zone overlay: 200
  • Minimap overlay (React): 5000
  • FPS counter: 9999
  • Tooltip: 10000

UIScaleManager

  • Single instance, scales fonts/boxes/images for accessibility
  • onScaleChange(callback) – when scale changes, createGameUI is re-run
  • Panel sizes (sidebar width, footer height) stay fixed; internal elements scale

StorageDriver

  • src/client/storage/StorageDriver.ts – abstracts getItem(key), setItem(key, val) for persistence
  • Default: localStorage (or sessionStorage for minimap overlay)
  • Used by: minimap position, overlay positions, UI scale, session data
  • Swappable via setStorageDriver() in init()

Key files (React layout)

File Role
react/main.tsx Entry, mounts App in #root
react/App.tsx Layout, init(), screen routing, canvas reparent
GameBridge.ts GameUIApi, SelectionEvent types
react/game/GameFooter.tsx Order manager, Colonists, Jobs tabs
react/game/overlays/GameOverlays.tsx Overlay container, selection → panel
react/game/overlays/DraggableOverlayPanel.tsx Generic draggable panel
react/game/panels/*.tsx ColonistPanel, ZonePanel, ObjectPanel, AreaSelectionPanel