LearnNewsExamplesServices
Frontmatter
titlerefactor(portal): promote canvas glue to shared Portal.view.content (#12206)
authorneo-opus-ada
stateMerged
createdAtMay 30, 2026, 10:46 PM
updatedAtMay 30, 2026, 11:03 PM
closedAtMay 30, 2026, 11:03 PM
mergedAtMay 30, 2026, 11:03 PM
branchesdevrefactor/portal-shared-canvas-glue-12206
urlhttps://github.com/neomjs/neo/pull/12224
Merged
neo-opus-ada
neo-opus-ada commented on May 30, 2026, 10:46 PM

Authored by Opus 4.8 (Claude Code). Session 94a91ebc.

Resolves #12206

Foundation step 2 of epic #12204. Promotes the App-worker canvas glue out of the tickets view into a shared portal-content home so the upcoming PR + Discussion views reuse it via config.

  • Relocates the bridge Portal.view.news.tickets.TimelineCanvasPortal.view.content.TimelineCanvas and the wrapper ...tickets.CanvasWrapperPortal.view.content.CanvasWrapper (into apps/portal/view/content/).
  • Removes CanvasWrapper's only per-type coupling — the hardcoded import Component from './Component.mjs' default. contentComponent now defaults to null; consumers supply it through the existing config seam.
  • The tickets MainContainer now imports the shared CanvasWrapper and passes its own Component as contentComponent via pageContainerConfig.contentConfig.
  • Generalizes the wrapper cls neo-ticket-timeline-wrapperneo-timeline-wrapper (per-type prefixes stay).

Per the operator's call, the shared home is portal-scoped (Portal.view.content.*), not framework — #12208 still adds the Neo.app.content.Component base these extend, keeping the framework-API commitment to one deliberate step.

FAIR-band: over-target — sole active implementer on an operator-directed lane (epic #12204).

Evidence: L1 — grep for the old view.news.tickets.{TimelineCanvas,CanvasWrapper} ns + tickets/CanvasWrapper import == 0; node --check passes on the bridge, wrapper, and MainContainer; git records both files as renames (content preserved). The sections store key and .neo-timeline-item[data-record-id] selector are untouched (canvas-bridge contract, per AC). Residual: L2 — Tickets tab renders + animates unchanged (post-merge/deploy).

Deltas from ticket (if any)

  • Shared home is apps/portal/view/content/ (Portal.view.content.*), per the operator's portal-shared decision over the framework (src/app/content/) option.

Test Evidence

  • grep -rn "view.news.tickets.TimelineCanvas|...CanvasWrapper|tickets/CanvasWrapper" apps/portal → 0 matches.
  • node --check on view/content/TimelineCanvas.mjs, view/content/CanvasWrapper.mjs, view/news/tickets/MainContainer.mjs → pass.
  • sections store key + .neo-timeline-item[data-record-id] selector present and unchanged.

Post-Merge Validation

  • Tickets tab timeline still renders + animates (behavior-neutral relocation).

🤖 Generated with Claude Code