36 — Interaction & Navigation Patterns (envisioning)
Envisioning doc — needs confirmation. Governed by
00-ROADMAP.md. Created 2026-06-20 (owner-raised, off the doc-33 roll-up). The cross-cutting "how does touch behave" layer: how you navigate to a thing from a reference to it, how text responds to touch (select / copy / edit), and what "I saw this" means. Grounded in the actors (12), the Portals/lenses model (26), the design system (22), and the professional-calm brand (31). Nothing built from this doc yet beyond the backend provenance it enables.
What triggered this
Reviewing the doc-33 roll-up: a rolled-up comment didn't say where it came from ("Project / Track / V#"), and the owner expected to tap it and be taken to its place — but with a confirmation (a button / bubble / message), not a blind jump. Plus: text should be touch-sensitive (select, copy, edit in place), and the system should capture a "view" event, not only status changes. These are one family: references become destinations, and touch is the verb.
Principle: a reference carries its provenance and is a portal to its source
Every time we show a reference to something that lives elsewhere — a rolled-up comment, a note, a search hit, an activity row, a shared item — it must (a) say what it is and where it lives (provenance) and (b) be navigable to that exact place (a portal to the source). One pattern, reused everywhere.
Provenance — the source path is always shown
A rolled-up annotation reads, e.g.: 💬 LOVERE › Demo Place › Track 3 › V2 · 2d ago · "fix the low end". The kind chip (📝 note vs 💬 feedback) + the breadcrumb (roster › artist › project › track › version, trimmed to what's relevant at this altitude) answer "what / where" before you tap. (Backend now serves this: the roll-up items populate track/project names + file.version — doc 33.)
Navigation — tap to locate, with a confirmation step (the owner's ask)
A tap must not blind-jump and lose the user's place. Recommended pattern — peek then go:
- Tap a reference → it expands in place (a "peek": full content + the provenance breadcrumb + the timecode for feedback) with an explicit "Open in {location} →" affordance. The expand is the confirmation — cheap, reversible, shows context.
- Tap "Open →" → navigate to the exact anchor:
- feedback (timeline comment) → the track's Wave, seeking to
timeStart, the comment focused. - note → the anchor node's Portal, the note focused.
- feedback (timeline comment) → the track's Wave, seeking to
- Long-press a reference → context menu ("Open location", "Copy", "Edit" if yours, "Resolve") — the iOS-native secondary path; pairs with touch-text below.
Don't auto-navigate on a single tap from a digest surface — the digest's job is overview; navigation is a deliberate second act (professional calm: the app doesn't yank you around). On a focused surface (the node's own thread) a single tap-to-seek is fine — there's no context to lose.
The hierarchy is symmetric (the owner's "which way around?")
A comment is authored on a version (File) in the Wave; it then rolls up for visibility — version → track → project → artist → roster — and you navigate down from any of those levels back to the exact version. Up = aggregation (the eagle view); down = location (the tap). Same edge, two directions.
Roster needs a Portal. Roster is today only a label+color grouping (doc 26 Layer 1). To host the roster-level roll-up band (and roster metadata / its own identity), Roster joins "Portals everywhere" (doc 26 Layer 4) — a lightweight Portal whose body is the cross-artist digest. Flag for the Portals phase.
Navigation transitions — carry the gradient across the push (owner-raised 2026-06-21)
Moving between hierarchy levels (artist → project → track → version, and back) currently pops — a stock push — which fights the identity gradient/halo painted at the top of every screen. The owner wants the transition to zoom / fade so the gradient feels continuous, not reset. This is not new vision — it's the unbuilt navigation half of two owner-locked principles:
- doc 22 §4 — "nothing pops; transitions interpolate." Continuous, driven motion over boolean cuts.
- doc 22 §6 — halo continuity down the chain. The halo already crossfades from the parent's identity color → the child's cover color (Artist → Project → Track → Version; doc 24 backlog). The screen transition should ride the same continuity.
The model — the cover is the through-line. Tapping an artist/project/track tile should feel like zooming into that cover: the tapped artwork expands into the destination's hero, and the ScreenBackground halo carries the gradient through the push (parent color already present → settles to the child's). Back = the reverse zoom-out. Net: one continuous gradient across the whole browse stack, the artwork as the spatial anchor — Liquid-Glass-native, on-brand calm.
- Best-practice (iOS 18+):
NavigationLink/navigationDestinationwith **.navigationTransition(.zoom).matchedTransitionSource** on the tapped cover → the destination hero. The halo is already identity- keyed (doc 22 §6), so it interpolates for free across the push instead of re-fading. Graceful fallback on older OS = a quick cross-fade (still no pop).
- Scope/where: the browse hierarchy pushes (Home→Artist→Project→Track→Player) — a design-heavy, layout-critical slice (Claude Code per the routing rule), shared via a small reusable transition modifier so every level uses one mechanism (not per-screen invention). Roadmap it as its own polish slice; it touches every browse navigation and wants careful tuning against the halo timing (don't double-animate).
Decision flagged below (#5). Until built, pushes stay stock; nothing here blocks other work.
Touch-text sensitivity — select / copy / edit in place
Text is not inert. The documented contract:
- Any annotation/metadata text is selectable + copyable (
.textSelection(.enabled)) — a reviewer copies a lyric line, a manager copies an ISRC. Zero-cost, expected. - Owned text is editable in place — your own note/comment/metadata shows a subtle edit affordance (tap to enter an inline field, or long-press → "Edit"); not-owned text is read-only (roles gate). Edits are the existing
PUT /comment/:id/ metadata PATCH — no new backend. - Consistent affordance, not per-screen invention — the same "tap-to-edit / long-press-for-actions" verb everywhere, so the user learns it once (design-system level — belongs in
22).
"View" events — seen-state, not only status
The owner: "we will require to get the event of 'view', not only action taken of status." Distinct from approvals/resolves (an action), a view is a passive seen signal — who has actually looked at this version / comment / note. Value (B2B, doc 31): "the producer has seen my revision request," "3 of 4 approvers have opened the master." This is read-receipts for the catalog.
- Model (envision): a per-(user, node) seen record —
{ user, nodeType, nodeId, lastSeenAt }— set when a node is actually viewed (debounced, on meaningful dwell, not on every scroll). Drives "unseen" dots, "seen by N", and an unseen filter on the roll-up (a strong default lens: "new since I last looked"). - Distinct from doc-35 events (which broadcast mutations) and from notifications (which alert on events). A view is neither — it's accumulated state. New surface; its own slice.
- Privacy/quiet: seen-state is calm by default (a dot, not a notification); "seen by" detail is opt-in per the fair-credit/professional-calm posture (doc 31). Decide visibility rules at build time.
How this sequences
- Shipped now (backend): roll-up item provenance (
track/projectnames +file.versionon the roll-up items) — the data the breadcrumb + navigation need. - Next (iOS): the peek-then-go navigation + breadcrumb on roll-up items; touch-text select/copy + edit-in-place where owned. Rides the doc-33 badge+band slice.
- Later (envision): the Roster Portal; the "view"/seen subsystem (its own slice — per-user seen store + unseen lens).
Decisions — to confirm (flagged)
- Navigation gesture — peek-then-go (tap expands → "Open →"; recommend) vs single-tap-navigates vs long-press-only. Different per surface (digest = peek; focused thread = direct)?
- Edit affordance — inline tap-to-edit vs long-press → "Edit" vs a visible pencil. Pick one, apply everywhere.
- "View"/seen — build it? If so: granularity (per version? per comment?), what "counts" as a view (dwell threshold), and whether "seen by {who}" is visible or just an aggregate.
- Roster Portal — confirm Roster becomes a Portal node (doc 26 Layer 4) to host its roll-up + identity.
- Navigation transition — ✅ BUILT 2026-06-21 (zoom-into-cover,
.navigationTransition(.zoom)+matchedTransitionSourceacross all browse hops; halo carried through via doc-22 §6).xcodebuildgreen; ⏳ visual QA + halo-timing tuning pending. (Cross-fade fallback happens automatically when no source matches.)
Cross-references
- The roll-up that surfaces references:
33-NOTES-ANNOTATIONS.md§Eagle view / §Surfacing UX - Portals everywhere + lenses (the destinations):
26-IDENTITY-SHARING-NAVIGATION.md(Layers 2 & 4) - Design-system home for the touch verbs:
22-IOS-DESIGN-SYSTEM.md - Actors who navigate/edit/are-seen:
12-ACTORS-WORKFLOWS.md - Why calm + accountability:
31-PRODUCT-VISION-360.md