feat(m1): PR3 T3.0 — shell UI, action kinds, story tab #16
+39
-2
@@ -25,6 +25,12 @@ storage, requestAnimationFrame, or Date scheduling.
|
||||
resource and one timed action. M1 expands this into real resources, actions,
|
||||
story nodes, automation unlocks, and prestige definitions.
|
||||
|
||||
Each action carries a behavior `kind` (`instant`, `loop`, `timed`, `story`,
|
||||
`context`) and a `group` (`{ id, label }`) used for UI layout. The schema
|
||||
enforces kind-specific invariants: `timed`/`loop` require `durationMs`, `timed`
|
||||
requires at least one yield, and `story` requires a `storyChoiceId` linking the
|
||||
action to a choice on the current story node.
|
||||
|
||||
## State
|
||||
|
||||
`src/state/` owns environment coupling:
|
||||
@@ -42,8 +48,39 @@ story nodes, automation unlocks, and prestige definitions.
|
||||
## UI
|
||||
|
||||
`src/ui/` renders the view model and calls runtime commands. Components should
|
||||
not implement gameplay rules. The M0 shell includes a resource readout, action
|
||||
panel, progress bar, and event log.
|
||||
not implement gameplay rules.
|
||||
|
||||
### Shell layout
|
||||
|
||||
PR3 replaces the M0/PR2 single-column overlay with a three-region shell
|
||||
(`AppShell.tsx`): a left **nav rail** (Play / Story / Settings / About), a
|
||||
**center** panel for the active tab, and a **right rail** shown on Play
|
||||
(resources, an inventory placeholder, and an optional event log gated by the
|
||||
`showEventLog` pref). `store.activePanel` selects the center panel; there is no
|
||||
modal overlay. New story beats raise a nav badge (`storyHasUnread`), and
|
||||
`storyOpenMode: auto` switches to the Story tab instead of opening an overlay.
|
||||
|
||||
### Action kinds
|
||||
|
||||
Play organizes actions into **columns by behavior kind**, ordered
|
||||
`instant → loop → timed → story → context`, with collapsible theme **groups**
|
||||
inside each column (collapse state persists in `prefs.collapsedActionGroups`).
|
||||
The pure engine dispatches each kind through `performAction` (`game.ts`):
|
||||
`instant` applies costs/yields immediately, `timed` enqueues, `loop` toggles an
|
||||
entry in `enabledLoopActionIds` (an idle runner starts the highest-priority
|
||||
affordable loop only when the queue is empty and only during live ticks, never
|
||||
offline), and `story` applies the linked choice. Story forks are taken **only**
|
||||
through Story-kind actions; the Story tab itself is read-only.
|
||||
|
||||
### Story tab
|
||||
|
||||
`StoryView.tsx` is a read-only 60/40 split: a branching `StoryTree` built from
|
||||
the story graph's choice/trigger edges (seen paths emphasized, unseen dimmed) and
|
||||
a scrollable `StoryProseLog` with no choice buttons. The boot intro shows a
|
||||
single Continue affordance that advances `boot_intro → fork_choice`; thereafter
|
||||
progression is driven by Story-kind actions.
|
||||
|
||||
The full design lives in `docs/superpowers/specs/2026-06-11-m1-pr3-shell-ui-design.md`.
|
||||
|
||||
## Verification
|
||||
|
||||
|
||||
Reference in New Issue
Block a user