Commit Graph
2 Commits
Author SHA1 Message Date
archipelagoandClaude Fable 5 fa14f6ebaa feat(federation): GSAP-powered 3D orbital node map, fills viewport to bottom
- Add gsap 3.15 + design-system-aware motion module (src/utils/motion.ts):
  shared colour/duration/ease tokens mirrored from style.css, gsap.defaults,
  live prefers-reduced-motion check.
- Replace the d3 force NetworkMap with NetworkMap3D.vue: peers on projected
  3D orbital rings around the self node, cinematic intro (camera dolly +
  staggered fly-in + ring draw), idle rotation with drag-to-orbit inertia,
  depth-sorted painter's order, trust-colour palette, online/offline states,
  sonar pulse on self, tap-a-node opens the detail modal.
- Map view now fills the dashboard panel to the bottom edge on desktop,
  mobile and companion: .dashboard-scroll-panel:has(.node-map-stage) turns
  the panel into a column (tab-bar/safe-area/audio-player aware padding)
  instead of leaving the old dead bottom margin.
- Reduced motion: intro/idle skipped, scene renders static.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 17:09:09 -04:00
archipelagoandClaude Fable 5 abdfa07a77 feat(02-05): bound the Leaflet map's lifecycle across Mesh tab deactivation
Demo images / Build & push demo images (push) Failing after 3m45s
MeshMap.vue's onMounted setup (window resize listener + ResizeObserver)
is refactored into an idempotent armMapVisibility()/disarmMapVisibility()
pair, dual-registered on both onMounted and onActivated (onActivated is a
documented no-op outside a KeepAlive boundary) and torn down on
onDeactivated, matching the arm/disarm idiom Mesh.vue itself already uses.
The Leaflet instance is never destroyed or recreated by this — initMap()'s
own `if (!mapContainer.value || map) return` guard already makes
construction idempotent, so exactly one map is built per session. On
reactivation the map's size is invalidated via nextTick so a map laid out
while off screen re-tiles at its real size instead of showing an unsized
or partially tiled canvas.

FLAGGED: RESEARCH.md's premise that Mesh.vue owns a live D3 force
simulation does not hold for this codebase — a grep for
d3/forceSimulation/simulation across neode-ui/src found nothing in
Mesh.vue's or MeshMap.vue's tree; the only D3 force simulation belongs to
NetworkMap.vue (Federation.vue's graph, out of this plan's scope). The
plan's D3-specific truths are therefore vacuously satisfied — see
02-05-SUMMARY.md for detail. Only the real Leaflet-map lifecycle work
landed here.

meshMapLifecycle.test.ts is a new, separate file (not appended to
meshTabCache.test.ts) because its vi.mock('@/stores/mesh')/vi.mock('leaflet')
hoist file-wide and would otherwise clobber meshTabCache.test.ts's need for
the real mesh/transport stores — mirrors the MarketplaceRefresh.test.ts
precedent from 02-02 for the same class of vi.mock-hoisting conflict.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 16:16:40 -04:00