Skip to content

Panel internals

Overview

Sidebar panels live in src/client/ui/components/sidebar/panels/. Each panel is a PixiJS Container with a consistent layout: panel area below the minimap, full sidebar width, height to footer. Data is passed in via setColonistData, showZone, showObject, etc.; callbacks wire actions back to IsometricMap or GameArea.

Title bar and close: Above panel content, Sidebar draws a title bar (panel name + close button ×). Panel name is one of: Colonist, Workshop, Object, Zone, Area selection. Clicking × calls Sidebar.clearSelection(): clears map selection (selection border, last-clicked state via IsometricMap.clearSelection()), hides the panel, and hides zone overlay. Clicking an empty map tile does not close the panel or clear selection; only the × button (or selecting another object) does.


ColonistPanel (citizen)

When shown: Colonist selected (panelType === 'citizen'). File: panels/ColonistPanel.ts.

Data: ColonistData – id, name, age, skills, bodyParts, allowedJobTypes, needs.

Tabs:

Tab Content
Bio Name, age
Medical Body parts (name, condition, damage)
Gear ColonistPanelGearTab – equipment slots (placeholder)
Jobs Current job label + "Cancel job"; job type checkboxes (Chop, Mine, Haul) – call setColonistJobAllowed
Needs Need bars (sleeping, drinking, eating, recreation); "Go drink" / "Go sleep" buttons; optional debug set

Callbacks:

  • onForceDrink(colonistId) → IsometricMap.forceCreateDrinkJob (cancels current job, then creates drink job)
  • onForceSleep(colonistId) → IsometricMap.forceCreateSleepJob (cancels current job, then creates sleep job)
  • onJobPreferenceChange(colonistId, actionId, allowed) → IsometricMap.setColonistJobAllowed
  • onRefreshColonistData(colonistId) → IsometricMap.getColonistData (e.g. after job complete for XP update)
  • onSetColonistNeed(colonistId, needKey, value) → IsometricMap.setColonistNeed (debug)

Skills: Renders level and XP; XP-for-next-level from gameData/skills (getXPForNextLevel, getTotalXPForLevel). Tooltip on hover uses current colonist data.


ZonePanel

When shown: Zone selected (storage or sleeping). File: panels/ZonePanel.ts.

Data: ZoneData + optional storageSummary: Map<string, number> (e.g. wood_log → count).

Content:

  • Zone name: from instance zone.name, else zone type display name from sim/core ZoneTypeRegistry (createDefaultZoneTypeRegistry().get(zone.type).displayName), else raw zone.type
  • Tile count
  • Storage summary: item labels from gameData/objectTypes getObjectTypeDisplayLabel(type) (e.g. Wood logs: 12, Stone bricks: 5) (e.g. “Wood logs: 12, Stone bricks: 5”)
  • “Delete zone” button → onDeleteCallback(zoneId)

Used both in the sidebar slot and as an overlay on the game screen when a zone is selected (same component, same content).


ObjectPanel (object)

When shown: Map object selected (tree, stone chunk, resource) – panelType === 'object'.

Data: ObjectData – id, name, type, description, condition, location, properties, actions (id, name, description, duration).

Tabs: Overview, Properties.

Actions: Buttons per object.getActions(). Click → onActionExecuteCallback(objectId, actionId, objectX, objectY) → IsometricMap executes action (e.g. chop, mine) and creates job.


WorkshopPanel (workshop)

When shown: Structure/workshop selected – panelType === 'workshop'.

Data: WorkshopData – id, name, type, description, condition, workers, production, inventory, stats, orders, craftableItems.

Tabs: Overview, Orders, Inventory, Workers.

Content: Placeholder for production orders, worker slots, craftable items from itemRegistry. onOrderCreate(itemId, quantity) for adding orders (if wired).


AreaSelectionPanel

When shown: Area selection mode active (user chose an order like Chop/Mine and drew a rectangle).

Data: objectCounts: Map<objectType, number> (e.g. pine_tree → 5, stone_chunk → 2).

Content:

  • Summary of selected objects by type.
  • Action buttons (e.g. “Chop Wood”, “Mine”) – only for actions that apply to the selection.
  • Click action → onActionClick(actionId) → IsometricMap.executeActionOnSelection(actionId), which creates jobs for all selected objects that support that action, then exits area selection.

Display names: ACTION_DISPLAY_NAMES maps actionId (chop, mine) to label (“Chop Wood”, “Mine”).


Map right-click (PPM) context menu

Right-click on the map opens MapContextMenu (floating at cursor). Content depends on target:

  • Right-click on object (tree, stone, etc.): menu shows actions from object.getActions() (e.g. Chop wood, Mine). Choosing an action creates the corresponding job(s). If the colonist panel is open, those jobs are assigned only to that colonist (reservedForColonistId on ChopJob/MineJob; see OrderJobFactory.createOrderJobs(..., reservedForColonistId) and IsometricMap.executeAction(..., reservedForColonistId)).
  • Right-click on empty tile with colonist panel open: menu shows Move here. Creates a MoveToJob for the selected colonist (sim/core/jobs/move). No object actions are shown on empty tile.

Context menu is implemented in MapInputHandler (onRightClickAt), IsometricMap.handleRightClickAt / handleContextMenuChoose, and MapContextMenu.ts. Right-click uses skipCallback in SelectionManager.clearSelection(true) when closing the panel to avoid recursion with the deselect callback.


Common layout

  • Panel Y = minimapHeight + padding
  • Title bar = 28px high, panel name + × close button (see Overview)
  • Panel height = appHeight - panelY - footerHeight (content below title bar)
  • Width = sidebarWidth
  • Background: Panel (fillColor 0x0f0f0f, stroke 0x2a2a2a)
  • Tabs (if any): TabButton row at top
  • Content: scrollable or stacked in contentContainer below tabs

All panels use the shared Tooltip instance for hover text. Font sizes are responsive (e.g. calculateResponsiveFontSize(sidebarWidth, ...)).