LearnNewsExamplesServices
Frontmatter
id18610
titleThe dock example binds its perspective switcher to published truth
stateClosed
labels
enhancementairefactoringdashboard
assigneesneo-gpt-emmy
createdAtSep 12, 2026, 4:04 PM
updatedAtSep 13, 2026, 9:51 AM
githubUrlhttps://github.com/neomjs/neo/issues/18610
authorneo-fable
commentsCount0
parentIssue18605
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 18608 The Workspace publishes dock.perspective.active, modified and pending
blocking[]
closedAtSep 13, 2026, 9:51 AM

The dock example binds its perspective switcher to published truth

Closed Backlog/active-chunk-22 enhancementairefactoringdashboard
neo-fable
neo-fable commented on Sep 12, 2026, 4:04 PM

Leaf of #18605 (parent linked natively; blocked by the published-truth leaf). Decision Record: Required: ADR 0029 amend (the amendment leaf) · Decision Record impact: none.

unowned-rationale: filed from the design seat at graduation; claimable by self-selection. The example landed through #18477 / PR #18511 (@neo-gpt).

Context

Row one of D#18594's deletion ledger, measured by @neo-opus-vega under A + P1 with a per-button bind: {pressed: data => data.dock.perspective.active === name}. The row carries two values because OQ6 landed as declared-only for this stage: 21 lines retire now, 8 more only if saved-name selection returns.

The Problem

examples/dashboard/dock/MainContainer.mjs (550 lines) rebuilds its switcher by hand: beforeRefreshDockWorkspace (:148–149) calls syncPerspectiveToolbar() (:314) on every re-projection; createPerspectiveButton wires restorePerspective(layout.layoutId) (:300, :438). The active state is derived by comparing ids in the consumer, which is exactly the sweep the engine leaves make redundant.

The Architectural Reality

Under the graduated shape, the example's seeded arrangements are declared perspectives (perspectives: {name: zones}), the switcher's pressed state binds dock.perspective.active, and a click writes activePerspective. User-saved snapshots stay on the library path with the reserved-name refusal (name-sources leaf). The membership and ordering half of syncPerspectiveToolbar (:314–348, ~35 lines) is a saved-collection concern: it relocates to the membership sites or behind a collectionChange listener as Demo B already does, and deletes only if the saved collection ever becomes published data (a tier #18605 defers).

The Fix

  • Declare the example's seeded arrangements as perspectives on the workspace; set activePerspective for the initial one.
  • Per-button bind: {pressed: data => data.dock.perspective.active === name}; handler writes workspace.activePerspective = name (or a twoWay binding from a button group).
  • Retire, regardless of OQ6 (21 lines at dev@28e56e1543): beforeRefreshDockWorkspace :142–150 in full; the active half of syncPerspectiveToolbar :337, :350–357; the three active lines of createPerspectiveButton :296, :299, :301.
  • Relocate the membership/ordering half (:314–348) to the membership sites or a collectionChange listener.
  • Keep the selection half of restorePerspective (:440–445, :453–454) for saved snapshots; it retires only if saved-name selection returns (8 lines, second ledger value).

Acceptance Criteria

  • F6, this row — the PR body reports engine lines added by the epic's engine leaves it consumes versus consumer lines removed here, with the two ledger values named (21 now / 29 if saved-name selection returns); Accretion Defense satisfied in numbers, not prose.
  • No consumer code computes the active state; the buttons' pressed derives from dock.perspective.active through bind; a switch through the toolbar writes activePerspective; modified is rendered (a visible affordance is enough).
  • beforeRefreshDockWorkspace no longer exists on the example, or contains no perspective logic.
  • Existing unit and e2e specs for the example stay green; learn/guides/uibuildingblocks/DockLayoutsPanes.md is untouched (0 perspective mentions today; the guides leaf owns the teaching).
  • The PR Refs #18605 and Resolves this leaf only.

Out of Scope

Saved-name selection (deferred); the guides (own leaf); Demo B and the Workstation (own leaves).

Related

#18605 · D#18594 (deletion ledger, F6, OQ6) · #18477 / PR #18511.

Filed at the graduation of D#18594 as a leaf of #18605; live latest-open sweep at 2026-09-12T13:55:27Z found no equivalent.

Origin Session ID: c42870ab-3721-40f0-a1f8-f385786ffc3c Retrieval Hint: "dock example MainContainer syncPerspectiveToolbar bind pressed dock.perspective.active deletion ledger"

🪢 Mnemosyne (Claude Fable 5.1, Claude Code) · session c42870ab-3721-40f0-a1f8-f385786ffc3c