Skip to content

feat(template): multi-tab artifact viewing (issue #116)#127

Merged
fedorovvvv merged 6 commits into
developfrom
feat/issue-116-multi-tab-artifacts
May 9, 2026
Merged

feat(template): multi-tab artifact viewing (issue #116)#127
fedorovvvv merged 6 commits into
developfrom
feat/issue-116-multi-tab-artifacts

Conversation

@fedorovvvv
Copy link
Copy Markdown
Collaborator

Summary

  • New tabsStore (entities/artifact-tabs) + useOpen(event, id) hook centralise the Shift+click-vs-plain-click policy across every artifact-opening surface.
  • New TabBar widget (widgets/artifact-tabs) renders the open tabs above ArtifactPanel with per-tab close, fall-back-to-first when closing the active tab, and beforeunload clear (no persistence).
  • Graph multi-highlight: active tab keeps its orange selection-ring + edge accent (unchanged); every opened tab and its 1-hop neighbours stay fully opaque, with their incident edges no longer dimmed. Implemented by extending nodeClass (now takes visibleIds) and edgeClass (now takes openedIds); applied uniformly to all seven graph views (Force, Tree, Radial, Lanes, Matrix, Sankey, Sunburst).

Closes #116.

Why

Reviewers and maintainers walking a chain of linked artifacts (PRD → RFC → ADR → evidence) lose scroll position and re-fetch on every plain click. Tabs make the comparison stateless and the linked context visible in the graph at all times.

Test plan

  • npm run check — 0 errors, 0 warnings (svelte-kit sync + svelte-check, 1064 files).
  • npm run builddist/ and dist-nightly/ produced (~1.41M each, both stable + nightly images).
  • Browser smoke (chrome MCP, dev server at 127.0.0.1:5174):
    • AC-1 Shift+click adds tab → strip grows, active stays, both nodes highlighted.
    • AC-2 Plain click replaces active → ADR-003* → ADR-004*; non-active tabs untouched.
    • AC-3 Close active falls back to first remaining; close inactive just drops it.
    • AC-4 Close last → panel hidden, all node highlights cleared.
    • AC-5 Reload → strip empty, panel hidden.
    • All entry points honour Shift: graph node click, keyboard Shift+Enter, rail row, in-panel NodeRef chip.
    • 4 tabs in Force view → 1 selection-ring (active only), 2 orange edges (active-incident), ~5 plain edges (other-opened-incident, no dim), 10 visible nodes (opened + 1-hop), 89 dimmed.
    • 0 console errors throughout the entire walk.

Forgeplan

PRD-032 active, EVID-037 active (verdict supports / congruence_level 3 / evidence_type test) → R_eff = 1.0 for PRD-032.

🤖 Generated with Claude Code

fedorovvvv and others added 6 commits May 9, 2026 16:27
Closes #116.

Adds an array-backed "open tabs" store (`tabsStore`) and a centralised
`useOpen(event, id)` hook so every artifact-opening surface (graph node,
rail row, in-panel link, NodeRef chip, breadcrumb) honours the same
modifier policy: Shift+click adds a new tab without dropping the active,
plain click replaces the active tab. A `TabBar` widget renders above
`ArtifactPanel` with per-tab close buttons; closing the active tab falls
back to the first remaining; closing the last hides the panel. The store
is intentionally unpersisted — `beforeunload` clears it so reload starts
clean.

Graph view highlights every artifact in the tab strip via two layers:
the active tab gets the existing orange selection-ring + edge highlights
(unchanged behaviour); inactive opened tabs and any 1-hop neighbour stay
fully opaque (no BFS dimming) and edges incident to any opened node lose
the dim treatment. Achieved by extending `nodeClass` to accept a
`visibleIds` set and `edgeClass` to accept `openedIds`; each of the seven
graph views computes `visibleIds = adjacentToSet(openedIds, edges)` once
per render via `$derived`.

Wiring touches every entry point so `MouseEvent`/`KeyboardEvent` reaches
`useOpen` unchanged: `g.node` click + Enter/Space in all seven views,
`InsightsRail` row buttons, `ArtifactPanel.onNavigate` for in-body
NodeRef chips, `NodeRef.onSelect` itself.

Verified with `npm run check` (0 errors) and a browser smoke walk via
chrome MCP — all PRD-032 acceptance criteria (AC-1..AC-5) pass with no
console errors. EvidencePack EVID-037 records the run with structured
fields (verdict supports / CL3 / evidence_type test) → R_eff = 1.0.

Refs: PRD-032, EVID-037

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bump `.opened` box stroke-width from default 1px to 2.2px and label
font-weight to 600 across Force/Tree/Radial/Lanes views; apply equivalent
emphasis on Matrix row/col labels, Sankey bar stroke, and Sunburst arc
in the remaining views (where `.opened` was newly added). Active tab
keeps the orange selection-ring as the only orange cue; opened-but-not-
active now reads as "deliberately surfaced" against unopened background
without competing with active highlight.

Refs: PRD-032

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reworks the highlight gradient to pure opacity, per user feedback:
keep the orange selection-ring (and orange `edge-active` stroke) as
the only orange cue, reserved for the active tab + its incident edges;
everything else differentiates by opacity alone.

- `nodeClass(id, focusId, distances, openedIds, visibleIds)` now buckets
  in priority: opened (= openedIds) → `node-active` (opacity 1); 1-hop
  adjacent (= visibleIds) → `node-near`; otherwise the existing
  hover-distance fallback.
- Drops the `.opened` stroke-width / font-weight overrides added in
  the previous commit so the only visual cue between "opened" and
  "background" is opacity.
- Tightens focus-soft opacity gradient so opened-vs-adjacent is
  distinguishable: `node-near` 0.7 (was 0.92), `node-mid` 0.5 (0.75),
  `node-far` 0.38 (0.64), `node-outside` 0.28 (0.56),
  `edge-dim` 0.32 (0.62) — and the base `.edge-dim` opacity drops to
  0.18 from 0.44 so dimmed edges fade further.
- `.edge-active` no longer bumps stroke-width to 2 — only the colour
  changes to var(--accent), so opened-incident and active-incident
  edges read at the same visual weight, with orange the only diff.

Refs: PRD-032

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…atrix

In Sankey/Sunburst the active selection bumps `.bar`/`.arc`
fill-opacity from the base 0.78 to 1 plus an accent stroke and glow,
while opened (non-active) tabs got nothing → opened bars looked dimmer
than active even though both were "opened". Match active's fill-opacity
on `.opened` so the only visual diff is the orange stroke/glow that
marks the active. Matrix gets a parallel cue: the row/col label
underline now also paints on `.opened` (in `var(--fg)`), reserving
accent-coloured underlining for `.selected`.

Refs: PRD-032

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sankey's `.link` base stroke-opacity is 0.36 (intentional ambient mute);
`.edge-active` overrides to 0.92. Opened-incident edges previously had
no class → fell back to 0.36, so edges flowing into opened-but-not-active
nodes (ADR-001/2/3 in the user's screenshot) read at less than half the
visibility of edges incident to the active node.

`edgeClass` now returns a dedicated `edge-on` class for opened-incident
edges (instead of empty string). SankeyView styles `.link.edge-on` at
the same 0.92 stroke-opacity as `edge-active` — matching brightness, no
accent colour. Force/Tree/Radial/Lanes already render edges at default
full opacity so no CSS change there; the new class is a no-op there
unless a future view wants to differentiate.

Refs: PRD-032

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Force/Tree/Radial/Lanes selection-ring + `.node.selected .box` filters
were using `drop-shadow(0 0 8px currentColor)`. In light theme
`currentColor` resolves to the inherited foreground (near-black) instead
of the accent, producing a dark gray halo around the active node next
to the orange ring. Pin the drop-shadow colour to `var(--accent)` so
the glow is always primary across themes.

Refs: PRD-032

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fedorovvvv fedorovvvv merged commit 696adb4 into develop May 9, 2026
3 checks passed
@fedorovvvv fedorovvvv deleted the feat/issue-116-multi-tab-artifacts branch May 9, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant