@sleep2agi/agent-network-dashboard 0.5.1-preview.2 → 0.5.1-preview.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/diagnostics/route-bundle-stats.json +6 -6
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_not-found.html +2 -2
- package/.next/server/app/_not-found.rsc +2 -2
- package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/server/app/admin.html +2 -2
- package/.next/server/app/admin.rsc +2 -2
- package/.next/server/app/admin.segments/_full.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_head.segment.rsc +1 -1
- package/.next/server/app/admin.segments/_index.segment.rsc +2 -2
- package/.next/server/app/admin.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/admin.segments/admin/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/admin.segments/admin.segment.rsc +1 -1
- package/.next/server/app/index.html +2 -2
- package/.next/server/app/index.rsc +3 -3
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/login.html +2 -2
- package/.next/server/app/login.rsc +3 -3
- package/.next/server/app/login.segments/_full.segment.rsc +3 -3
- package/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/server/app/login.segments/_index.segment.rsc +2 -2
- package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/server/app/logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/logs.html +2 -2
- package/.next/server/app/logs.rsc +2 -2
- package/.next/server/app/logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/logs.segments/logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/logs.segments/logs.segment.rsc +1 -1
- package/.next/server/app/messages/page_client-reference-manifest.js +1 -1
- package/.next/server/app/messages.html +2 -2
- package/.next/server/app/messages.rsc +2 -2
- package/.next/server/app/messages.segments/_full.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_head.segment.rsc +1 -1
- package/.next/server/app/messages.segments/_index.segment.rsc +2 -2
- package/.next/server/app/messages.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/messages.segments/messages/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/messages.segments/messages.segment.rsc +1 -1
- package/.next/server/app/node/page_client-reference-manifest.js +1 -1
- package/.next/server/app/node.html +2 -2
- package/.next/server/app/node.rsc +2 -2
- package/.next/server/app/node.segments/_full.segment.rsc +2 -2
- package/.next/server/app/node.segments/_head.segment.rsc +1 -1
- package/.next/server/app/node.segments/_index.segment.rsc +2 -2
- package/.next/server/app/node.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/node.segments/node/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/node.segments/node.segment.rsc +1 -1
- package/.next/server/app/nodes/page_client-reference-manifest.js +1 -1
- package/.next/server/app/nodes.html +2 -2
- package/.next/server/app/nodes.rsc +2 -2
- package/.next/server/app/nodes.segments/_full.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_head.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/_index.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/nodes.segments/nodes/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/nodes.segments/nodes.segment.rsc +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs/page_client-reference-manifest.js +1 -1
- package/.next/server/app/server-logs.html +2 -2
- package/.next/server/app/server-logs.rsc +2 -2
- package/.next/server/app/server-logs.segments/_full.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_head.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/_index.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/server-logs.segments/server-logs/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/server-logs.segments/server-logs.segment.rsc +1 -1
- package/.next/server/app/settings/networks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/networks.html +2 -2
- package/.next/server/app/settings/networks.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/networks.segments/settings/networks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings/networks.segment.rsc +1 -1
- package/.next/server/app/settings/networks.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens/page_client-reference-manifest.js +1 -1
- package/.next/server/app/settings/tokens.html +2 -2
- package/.next/server/app/settings/tokens.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_full.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings/tokens.segments/settings/tokens/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings/tokens.segment.rsc +1 -1
- package/.next/server/app/settings/tokens.segments/settings.segment.rsc +1 -1
- package/.next/server/app/settings.html +2 -2
- package/.next/server/app/settings.rsc +3 -3
- package/.next/server/app/settings.segments/_full.segment.rsc +3 -3
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +2 -2
- package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/tasks/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks/page_client-reference-manifest.js +1 -1
- package/.next/server/app/tasks.html +2 -2
- package/.next/server/app/tasks.rsc +2 -2
- package/.next/server/app/tasks.segments/_full.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_head.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/_index.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/_tree.segment.rsc +2 -2
- package/.next/server/app/tasks.segments/tasks/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/tasks.segments/tasks.segment.rsc +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js +3 -3
- package/.next/server/chunks/ssr/agent-network-dashboard_09kk21a._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_01jhlxz._.js.map +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js +1 -1
- package/.next/server/chunks/ssr/agent-network-dashboard_app_09d29my._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/500.html +1 -1
- package/.next/static/chunks/00il-zdt_kaju.js +1 -0
- package/.next/static/chunks/0sad-q2~jp3md.js +1 -0
- package/.next/static/chunks/0~oj~gm3ck7o8.css +2 -0
- package/.next/static/chunks/12xcj8aufgn.~.js +4 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +366 -42
- package/package.json +1 -1
- package/scripts/topo-active-links-freshness-color-test.mjs +86 -0
- package/scripts/topo-filter-pill-hover-opacity-test.mjs +110 -0
- package/scripts/topo-filter-pill-weight-test.mjs +75 -0
- package/scripts/topo-filter-pill-x-hover-scale-test.mjs +99 -0
- package/scripts/topo-freshness-floor-lift-test.mjs +92 -0
- package/scripts/topo-freshness-suffix-tabular-test.mjs +88 -0
- package/scripts/topo-fullscreen-icon-hover-scale-test.mjs +91 -0
- package/scripts/topo-layout-toggle-hover-tracking-test.mjs +109 -0
- package/scripts/topo-minimap-viewport-hover-test.mjs +109 -0
- package/scripts/topo-more-flows-hover-letterspacing-test.mjs +98 -0
- package/scripts/topo-panel-count-letterspacing-test.mjs +89 -0
- package/scripts/topo-panel-rect-opacity-hover-test.mjs +109 -0
- package/scripts/topo-panel-title-hover-letterspacing-test.mjs +97 -0
- package/scripts/topo-recent-pip-radius-test.mjs +76 -0
- package/scripts/topo-reset-hover-rotate-test.mjs +102 -0
- package/scripts/topo-vendor-letter-hover-scale-test.mjs +129 -0
- package/scripts/topo-zoom-icon-hover-scale-test.mjs +114 -0
- package/scripts/topo-zoom-level-hover-letterspacing-test.mjs +91 -0
- package/.next/static/chunks/0aauz~36q5n2a.css +0 -2
- package/.next/static/chunks/0ap~cvzkt4_.w.js +0 -1
- package/.next/static/chunks/0bu~3a_lb2vr1.js +0 -4
- package/.next/static/chunks/14d3w289h5vr0.js +0 -1
- /package/.next/static/{U2ie3REU1St9mnDvCTXzE → R-2OMhJQbEOhvciFPHB8c}/_buildManifest.js +0 -0
- /package/.next/static/{U2ie3REU1St9mnDvCTXzE → R-2OMhJQbEOhvciFPHB8c}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{U2ie3REU1St9mnDvCTXzE → R-2OMhJQbEOhvciFPHB8c}/_ssgManifest.js +0 -0
|
@@ -1026,6 +1026,42 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
1026
1026
|
// navigation footer. Drives the on-hover opacity boost + underline
|
|
1027
1027
|
// that signals interactivity, mirroring the hoveredHub idiom above.
|
|
1028
1028
|
const [hoveredRecentMore, setHoveredRecentMore] = useState(false);
|
|
1029
|
+
// Round 346 / Loop: minimap-container hover affordance. The minimap
|
|
1030
|
+
// is a click-target (role=button at line ~7810, recenter-on-click +
|
|
1031
|
+
// Enter→resetView) but pre-R346 nothing visually changed on hover —
|
|
1032
|
+
// the only hint was the `cursor: crosshair` style. R346 lifts the
|
|
1033
|
+
// viewport rect (strokeWidth 1.5 → 1.75 + opacity 0.9 → 1.0) when
|
|
1034
|
+
// the user enters the minimap, marking "this is the recenter target
|
|
1035
|
+
// and it's alive". Sibling polish to the R332 minimap rounded-md →
|
|
1036
|
+
// rounded-lg corner family — that round refined geometry, this one
|
|
1037
|
+
// gives the viewport indicator inside the geometry a hover state.
|
|
1038
|
+
// 280ms ease-out transition list matches R199 smoothView vocabulary
|
|
1039
|
+
// so the visual joins the existing rhythm on the same rect.
|
|
1040
|
+
const [hoveredMinimap, setHoveredMinimap] = useState(false);
|
|
1041
|
+
// Round 347 / Loop: zoom-level readout hover-state letter-spacing
|
|
1042
|
+
// tween (0 → 0.5 px). The readout sandwiched between zoom-out /
|
|
1043
|
+
// zoom-in is a passive percent display — pre-R347 it had no hover
|
|
1044
|
+
// feedback at all (only a `title` tooltip). R347 extends the R344
|
|
1045
|
+
// (`+N more flows` footer) + R345 (panel titles) hover-letter-
|
|
1046
|
+
// spacing family from panel/footer surfaces into the HTML chrome
|
|
1047
|
+
// strip. Hovering the readout spreads its digits 0.5 px, signalling
|
|
1048
|
+
// "this is alive". tabular-nums + minWidth: 46 from R225 still lock
|
|
1049
|
+
// the column so the tween doesn't shove neighbouring controls.
|
|
1050
|
+
// 200ms ease-out joins the existing R264 color/border transition
|
|
1051
|
+
// list on the same span.
|
|
1052
|
+
const [hoveredZoomLevel, setHoveredZoomLevel] = useState(false);
|
|
1053
|
+
// Round 350 / Loop: reset-button icon hover-rotate preview of the
|
|
1054
|
+
// R184 click-spin. Pre-R350 hovering the reset button only changed
|
|
1055
|
+
// the button bg (white/5); the icon inside stayed perfectly still.
|
|
1056
|
+
// R350 nudges the icon -8° on hover — a tactile hint that this
|
|
1057
|
+
// button rotates the icon on click. When the click fires, the
|
|
1058
|
+
// R184 anet-reset-spin keyframe animation overrides the hover
|
|
1059
|
+
// transform for its 450 ms run (CSS animations win over transitions
|
|
1060
|
+
// on the same property); when the animation ends + React removes
|
|
1061
|
+
// the className, the inline transform eases back to whatever the
|
|
1062
|
+
// hover state says — either -8° (still hovering) or 0 (mouse left).
|
|
1063
|
+
// 350th-round milestone polish.
|
|
1064
|
+
const [hoveredReset, setHoveredReset] = useState(false);
|
|
1029
1065
|
// R135: panel-wide hover-elevation. The recent-signal + legend
|
|
1030
1066
|
// panels both already host clickable rows (R56/R116 recent rows,
|
|
1031
1067
|
// R55/R61 legend rows) and a clickable footer (R133), so the
|
|
@@ -1826,7 +1862,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
1826
1862
|
weight; cyan-400/60 + ring-inset retained. The
|
|
1827
1863
|
R163/R196 hover/active deeps + R249 chrome-pop
|
|
1828
1864
|
click feedback continue unchanged. */
|
|
1829
|
-
|
|
1865
|
+
// R351: hover:tracking-wide extends the R344/R345/R347
|
|
1866
|
+
// hover-letter-spacing family to a 4th surface (chrome-
|
|
1867
|
+
// strip Ring/Grid pair). transition-colors className
|
|
1868
|
+
// dropped in favour of an inline transition spec that
|
|
1869
|
+
// bundles bg/color (150ms ease) + letter-spacing
|
|
1870
|
+
// (200ms ease-out) — Tailwind's transition-colors
|
|
1871
|
+
// doesn't list letter-spacing, so without this the
|
|
1872
|
+
// hover:tracking-wide would snap. Sibling change on
|
|
1873
|
+
// the Grid button below.
|
|
1874
|
+
className={`px-2.5 py-1 focus:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 focus-visible:ring-inset hover:tracking-wide ${layout === 'ring' ? 'bg-cyan-500/15 text-cyan-300 font-medium hover:bg-cyan-500/20 active:bg-cyan-500/25' : 'text-gray-400 hover:text-cyan-300 hover:bg-cyan-500/5 active:bg-cyan-500/15'} ${chromePopping === 'layout-ring' ? ' anet-chrome-pop' : ''}`}
|
|
1875
|
+
style={{ transition: 'background-color 150ms ease, color 150ms ease, letter-spacing 200ms ease-out' }}
|
|
1830
1876
|
>
|
|
1831
1877
|
Ring
|
|
1832
1878
|
</button>
|
|
@@ -1843,14 +1889,20 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
1843
1889
|
// Round 306 / Loop: focus-visible:ring-2 → ring-1 sibling
|
|
1844
1890
|
// change to Ring above — unifies focus-ring width across
|
|
1845
1891
|
// all chrome buttons.
|
|
1846
|
-
|
|
1892
|
+
// R351 sibling — Grid button picks up hover:tracking-wide
|
|
1893
|
+
// + inline transition spec. Same vocabulary as Ring.
|
|
1894
|
+
className={`px-2.5 py-1 border-l focus:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 focus-visible:ring-inset hover:tracking-wide ${layout === 'grid' ? 'bg-cyan-500/15 text-cyan-300 font-medium hover:bg-cyan-500/20 active:bg-cyan-500/25' : 'text-gray-400 hover:text-cyan-300 hover:bg-cyan-500/5 active:bg-cyan-500/15'} ${chromePopping === 'layout-grid' ? ' anet-chrome-pop' : ''}`}
|
|
1847
1895
|
/* Round 268 / Loop: Grid button's left border (the
|
|
1848
1896
|
internal divider between Ring and Grid) picks up
|
|
1849
1897
|
pal.containerBorder, matching the wrapper change at
|
|
1850
1898
|
line ~1460 and the chrome strip's segmented borders
|
|
1851
|
-
(nodeSize, zoom). transition-colors className
|
|
1852
|
-
the border-color
|
|
1853
|
-
|
|
1899
|
+
(nodeSize, zoom). The R268 transition-colors className
|
|
1900
|
+
used to carry the border-color ease; R351 unfolds the
|
|
1901
|
+
transition list into the inline spec below so the
|
|
1902
|
+
letter-spacing tween rides alongside without snapping
|
|
1903
|
+
the border-color flip — border-color 200ms ease-out
|
|
1904
|
+
keeps R268's theme-toggle smoothness intact. */
|
|
1905
|
+
style={{ borderColor: pal.containerBorder, transition: 'background-color 150ms ease, color 150ms ease, border-color 200ms ease-out, letter-spacing 200ms ease-out' }}
|
|
1854
1906
|
>
|
|
1855
1907
|
Grid
|
|
1856
1908
|
</button>
|
|
@@ -2259,7 +2311,10 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2259
2311
|
data-active-filter="status"
|
|
2260
2312
|
data-filter-match-count={matchCount}
|
|
2261
2313
|
data-filter-match-aliases={matchAliases.join(',')}
|
|
2262
|
-
|
|
2314
|
+
// R355: `group` lets the inner opacity-70 spans (prefix
|
|
2315
|
+
// `filter:` + count `· N`) brighten to 100 % on pill hover.
|
|
2316
|
+
// Sibling treatment on group + vendor pills below.
|
|
2317
|
+
className="group inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md font-mono font-medium text-xs border anet-fade-in anet-topo-chip-focus"
|
|
2263
2318
|
title={matchCount > 0 ? `${matchPreview}${matchSuffix} — click to clear` : 'Click to clear filter'}
|
|
2264
2319
|
onClick={() => setPinnedStatus(null)}
|
|
2265
2320
|
style={{
|
|
@@ -2273,12 +2328,26 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2273
2328
|
cursor: 'pointer',
|
|
2274
2329
|
}}
|
|
2275
2330
|
>
|
|
2276
|
-
<span><span className="hidden sm:inline opacity-70" data-filter-prefix>filter: </span>{pinnedStatus}<span className="opacity-70 tabular-nums" data-filter-pill-count> · {matchCount}</span></span>
|
|
2331
|
+
<span><span className="hidden sm:inline opacity-70 transition-opacity duration-200 group-hover:opacity-100" data-filter-prefix>filter: </span>{pinnedStatus}<span className="opacity-70 tabular-nums transition-opacity duration-200 group-hover:opacity-100" data-filter-pill-count> · {matchCount}</span></span>
|
|
2277
2332
|
<button
|
|
2278
2333
|
type="button"
|
|
2279
2334
|
aria-label={`Clear ${pinnedStatus} filter`}
|
|
2280
2335
|
onClick={(e) => { e.stopPropagation(); setPinnedStatus(null); }}
|
|
2281
|
-
|
|
2336
|
+
/* Round 356 / Loop: filter pin pill × buttons gain
|
|
2337
|
+
hover:scale-110 (Tailwind 4 modern CSS `scale` property,
|
|
2338
|
+
not legacy transform). Sibling polish to R354 vendor
|
|
2339
|
+
letter glyph + R350/R352/R353 chrome icon hover-scales.
|
|
2340
|
+
Pre-R356 the × had only hover:opacity-70 — the target
|
|
2341
|
+
dimmed under cursor but didn't lift. R356 adds a 10 %
|
|
2342
|
+
scale on hover so the click-target reads as "press me"
|
|
2343
|
+
alongside the dim. transform-gpu hint promotes the
|
|
2344
|
+
button to its own compositor layer for crisper edges
|
|
2345
|
+
during the scale tween. transition-transform duration-
|
|
2346
|
+
200 matches the chrome icon hover-scale timing family.
|
|
2347
|
+
inline-block is default for <button> so no display
|
|
2348
|
+
tweak needed. replace_all covers all 4 filter pin
|
|
2349
|
+
pills (status / group / vendor / edge) at once. */
|
|
2350
|
+
className="ml-0.5 leading-none hover:opacity-70 transition-transform duration-200 ease-out hover:scale-110 transform-gpu"
|
|
2282
2351
|
style={{ background: 'transparent', color: 'inherit', cursor: 'pointer', padding: 0 }}
|
|
2283
2352
|
>×</button>
|
|
2284
2353
|
</span>
|
|
@@ -2297,7 +2366,8 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2297
2366
|
data-active-filter="group"
|
|
2298
2367
|
data-filter-match-count={matchCount}
|
|
2299
2368
|
data-filter-match-aliases={matchAliases.join(',')}
|
|
2300
|
-
|
|
2369
|
+
// R355 sibling — `group` parent + group-hover on inner spans.
|
|
2370
|
+
className="group inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md font-mono font-medium text-xs border anet-fade-in anet-topo-chip-focus"
|
|
2301
2371
|
title={matchCount > 0 ? `${matchPreview}${matchSuffix} — click to clear` : 'Click to clear filter'}
|
|
2302
2372
|
onClick={() => setPinnedGroup(null)}
|
|
2303
2373
|
style={{
|
|
@@ -2307,12 +2377,26 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2307
2377
|
cursor: 'pointer',
|
|
2308
2378
|
}}
|
|
2309
2379
|
>
|
|
2310
|
-
<span><span className="hidden sm:inline opacity-70" data-filter-prefix>filter: </span>{pinnedGroup}<span className="opacity-70 tabular-nums" data-filter-pill-count> · {matchCount}</span></span>
|
|
2380
|
+
<span><span className="hidden sm:inline opacity-70 transition-opacity duration-200 group-hover:opacity-100" data-filter-prefix>filter: </span>{pinnedGroup}<span className="opacity-70 tabular-nums transition-opacity duration-200 group-hover:opacity-100" data-filter-pill-count> · {matchCount}</span></span>
|
|
2311
2381
|
<button
|
|
2312
2382
|
type="button"
|
|
2313
2383
|
aria-label={`Clear group filter ${pinnedGroup}`}
|
|
2314
2384
|
onClick={(e) => { e.stopPropagation(); setPinnedGroup(null); }}
|
|
2315
|
-
|
|
2385
|
+
/* Round 356 / Loop: filter pin pill × buttons gain
|
|
2386
|
+
hover:scale-110 (Tailwind 4 modern CSS `scale` property,
|
|
2387
|
+
not legacy transform). Sibling polish to R354 vendor
|
|
2388
|
+
letter glyph + R350/R352/R353 chrome icon hover-scales.
|
|
2389
|
+
Pre-R356 the × had only hover:opacity-70 — the target
|
|
2390
|
+
dimmed under cursor but didn't lift. R356 adds a 10 %
|
|
2391
|
+
scale on hover so the click-target reads as "press me"
|
|
2392
|
+
alongside the dim. transform-gpu hint promotes the
|
|
2393
|
+
button to its own compositor layer for crisper edges
|
|
2394
|
+
during the scale tween. transition-transform duration-
|
|
2395
|
+
200 matches the chrome icon hover-scale timing family.
|
|
2396
|
+
inline-block is default for <button> so no display
|
|
2397
|
+
tweak needed. replace_all covers all 4 filter pin
|
|
2398
|
+
pills (status / group / vendor / edge) at once. */
|
|
2399
|
+
className="ml-0.5 leading-none hover:opacity-70 transition-transform duration-200 ease-out hover:scale-110 transform-gpu"
|
|
2316
2400
|
style={{ background: 'transparent', color: 'inherit', cursor: 'pointer', padding: 0 }}
|
|
2317
2401
|
>×</button>
|
|
2318
2402
|
</span>
|
|
@@ -2347,7 +2431,8 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2347
2431
|
data-active-filter="vendor"
|
|
2348
2432
|
data-filter-match-count={matchCount}
|
|
2349
2433
|
data-filter-match-aliases={matchAliases.join(',')}
|
|
2350
|
-
|
|
2434
|
+
// R355 sibling — `group` parent + group-hover on inner spans.
|
|
2435
|
+
className="group inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md font-mono font-medium text-xs border anet-fade-in anet-topo-chip-focus"
|
|
2351
2436
|
title={matchCount > 0 ? `${matchPreview}${matchSuffix} — click to clear` : 'Click to clear vendor filter'}
|
|
2352
2437
|
onClick={() => setPinnedVendor(null)}
|
|
2353
2438
|
style={{
|
|
@@ -2357,12 +2442,26 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2357
2442
|
cursor: 'pointer',
|
|
2358
2443
|
}}
|
|
2359
2444
|
>
|
|
2360
|
-
<span><span className="hidden sm:inline opacity-70" data-filter-prefix>filter: </span>{pinnedVendor}<span className="opacity-70 tabular-nums" data-filter-pill-count> · {matchCount}</span></span>
|
|
2445
|
+
<span><span className="hidden sm:inline opacity-70 transition-opacity duration-200 group-hover:opacity-100" data-filter-prefix>filter: </span>{pinnedVendor}<span className="opacity-70 tabular-nums transition-opacity duration-200 group-hover:opacity-100" data-filter-pill-count> · {matchCount}</span></span>
|
|
2361
2446
|
<button
|
|
2362
2447
|
type="button"
|
|
2363
2448
|
aria-label={`Clear vendor filter ${pinnedVendor}`}
|
|
2364
2449
|
onClick={(e) => { e.stopPropagation(); setPinnedVendor(null); }}
|
|
2365
|
-
|
|
2450
|
+
/* Round 356 / Loop: filter pin pill × buttons gain
|
|
2451
|
+
hover:scale-110 (Tailwind 4 modern CSS `scale` property,
|
|
2452
|
+
not legacy transform). Sibling polish to R354 vendor
|
|
2453
|
+
letter glyph + R350/R352/R353 chrome icon hover-scales.
|
|
2454
|
+
Pre-R356 the × had only hover:opacity-70 — the target
|
|
2455
|
+
dimmed under cursor but didn't lift. R356 adds a 10 %
|
|
2456
|
+
scale on hover so the click-target reads as "press me"
|
|
2457
|
+
alongside the dim. transform-gpu hint promotes the
|
|
2458
|
+
button to its own compositor layer for crisper edges
|
|
2459
|
+
during the scale tween. transition-transform duration-
|
|
2460
|
+
200 matches the chrome icon hover-scale timing family.
|
|
2461
|
+
inline-block is default for <button> so no display
|
|
2462
|
+
tweak needed. replace_all covers all 4 filter pin
|
|
2463
|
+
pills (status / group / vendor / edge) at once. */
|
|
2464
|
+
className="ml-0.5 leading-none hover:opacity-70 transition-transform duration-200 ease-out hover:scale-110 transform-gpu"
|
|
2366
2465
|
style={{ background: 'transparent', color: 'inherit', cursor: 'pointer', padding: 0 }}
|
|
2367
2466
|
>×</button>
|
|
2368
2467
|
</span>
|
|
@@ -2395,7 +2494,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2395
2494
|
data-filter-match-count={link.count}
|
|
2396
2495
|
data-filter-match-aliases={`${link.from},${link.to}`}
|
|
2397
2496
|
data-active-filter-edge-hot={isHot ? 'true' : 'false'}
|
|
2398
|
-
className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md font-mono text-xs border anet-fade-in anet-topo-chip-focus"
|
|
2497
|
+
className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-md font-mono font-medium text-xs border anet-fade-in anet-topo-chip-focus"
|
|
2399
2498
|
title={`${link.from} → ${link.to} (${link.count} msg${link.count === 1 ? '' : 's'}${isHot ? ', hot lane · ≥ 10' : ''}) — click to clear`}
|
|
2400
2499
|
onClick={() => setPinnedEdgeKey(null)}
|
|
2401
2500
|
style={{
|
|
@@ -2439,7 +2538,21 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2439
2538
|
type="button"
|
|
2440
2539
|
aria-label={`Clear edge filter ${link.from} → ${link.to}`}
|
|
2441
2540
|
onClick={(e) => { e.stopPropagation(); setPinnedEdgeKey(null); }}
|
|
2442
|
-
|
|
2541
|
+
/* Round 356 / Loop: filter pin pill × buttons gain
|
|
2542
|
+
hover:scale-110 (Tailwind 4 modern CSS `scale` property,
|
|
2543
|
+
not legacy transform). Sibling polish to R354 vendor
|
|
2544
|
+
letter glyph + R350/R352/R353 chrome icon hover-scales.
|
|
2545
|
+
Pre-R356 the × had only hover:opacity-70 — the target
|
|
2546
|
+
dimmed under cursor but didn't lift. R356 adds a 10 %
|
|
2547
|
+
scale on hover so the click-target reads as "press me"
|
|
2548
|
+
alongside the dim. transform-gpu hint promotes the
|
|
2549
|
+
button to its own compositor layer for crisper edges
|
|
2550
|
+
during the scale tween. transition-transform duration-
|
|
2551
|
+
200 matches the chrome icon hover-scale timing family.
|
|
2552
|
+
inline-block is default for <button> so no display
|
|
2553
|
+
tweak needed. replace_all covers all 4 filter pin
|
|
2554
|
+
pills (status / group / vendor / edge) at once. */
|
|
2555
|
+
className="ml-0.5 leading-none hover:opacity-70 transition-transform duration-200 ease-out hover:scale-110 transform-gpu"
|
|
2443
2556
|
style={{ background: 'transparent', color: 'inherit', cursor: 'pointer', padding: 0 }}
|
|
2444
2557
|
>×</button>
|
|
2445
2558
|
</span>
|
|
@@ -2750,7 +2863,40 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2750
2863
|
}
|
|
2751
2864
|
}}
|
|
2752
2865
|
>
|
|
2753
|
-
|
|
2866
|
+
{/* Round 354 / Loop: vendor letter glyph scales
|
|
2867
|
+
1.0 → 1.1 on hover. R88 already dims OTHER
|
|
2868
|
+
vendors on hover via canvas-wide opacity
|
|
2869
|
+
masking; R202 added a chip-level bg tint
|
|
2870
|
+
(color-mix 12 % alpha) so the chip itself
|
|
2871
|
+
responds. R354 closes the trio with a glyph-
|
|
2872
|
+
level lift: the focused vendor LETTER actively
|
|
2873
|
+
rises (transform scale) rather than the chip
|
|
2874
|
+
merely changing colour. Three layers of positive
|
|
2875
|
+
feedback on the hovered vendor + canvas-wide
|
|
2876
|
+
negative feedback on the others — a clean
|
|
2877
|
+
figure/ground separation.
|
|
2878
|
+
|
|
2879
|
+
display: inline-block is required for transform
|
|
2880
|
+
to apply (inline elements ignore transform).
|
|
2881
|
+
transformOrigin: 'center' so the glyph pivots
|
|
2882
|
+
around its centre instead of arcing from the
|
|
2883
|
+
baseline anchor. transition rides the existing
|
|
2884
|
+
Tailwind 4 transform/scale list (no new
|
|
2885
|
+
property — Tailwind already lists transform in
|
|
2886
|
+
the default transition-property set). 200ms
|
|
2887
|
+
matches the R202 chip bg-tint timing so the
|
|
2888
|
+
glyph lift and chip background ease in concert. */}
|
|
2889
|
+
<span
|
|
2890
|
+
data-vendor-letter-glyph={v.initial}
|
|
2891
|
+
data-vendor-letter-glyph-hover={hoveredVendor === v.initial ? 'true' : 'false'}
|
|
2892
|
+
style={{
|
|
2893
|
+
color: v.color,
|
|
2894
|
+
display: 'inline-block',
|
|
2895
|
+
transform: hoveredVendor === v.initial ? 'scale(1.1)' : 'scale(1)',
|
|
2896
|
+
transformOrigin: 'center',
|
|
2897
|
+
transition: 'transform 200ms ease-out',
|
|
2898
|
+
}}
|
|
2899
|
+
>{v.initial}</span>
|
|
2754
2900
|
{/* Round 333 / Loop: vendor count suffix `:{N}` joins
|
|
2755
2901
|
the R317 subordinate-text-lift family (gray-500 →
|
|
2756
2902
|
gray-400) plus picks up tabular-nums for digit
|
|
@@ -2909,14 +3055,46 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2909
3055
|
const alpha = ageSec <= 30
|
|
2910
3056
|
? 1
|
|
2911
3057
|
: ageSec <= 300
|
|
2912
|
-
? 1 - ((ageSec - 30) / 270) * 0.
|
|
2913
|
-
: 0.25
|
|
3058
|
+
? 1 - ((ageSec - 30) / 270) * 0.70 /* R358: floor 0.25 → 0.30 lift across 3 freshness scopes */
|
|
3059
|
+
: 0.30; /* R358: stale floor lifted 0.25 → 0.30 — 20% legibility bump while preserving fresh/stale ratio */
|
|
2914
3060
|
// Cyan dark / teal light to match palette legendAccent.
|
|
2915
3061
|
const dotColor = isLight
|
|
2916
3062
|
? `rgba(13, 148, 136, ${alpha.toFixed(2)})`
|
|
2917
3063
|
: `rgba(34, 211, 238, ${alpha.toFixed(2)})`;
|
|
3064
|
+
// Round 342 / Loop: active-links chip freshness suffix
|
|
3065
|
+
// wrapper text-gray-500 → text-gray-400 (R317
|
|
3066
|
+
// subordinate-text-lift family applied to chrome
|
|
3067
|
+
// inactive Layout toggle + R333 vendor count suffix).
|
|
3068
|
+
// The "last 5s ago" suffix is chip-subordinate
|
|
3069
|
+
// metadata; gray-500 sat near-invisible against the
|
|
3070
|
+
// chip's outer color, gray-400 lifts it into the band
|
|
3071
|
+
// where the eye reads it as deliberate freshness
|
|
3072
|
+
// annotation. The freshness DOT keeps its own inline
|
|
3073
|
+
// color: dotColor — the lift only affects the trailing
|
|
3074
|
+
// literal "last {rel}" text.
|
|
2918
3075
|
return (
|
|
2919
|
-
|
|
3076
|
+
// Round 357 / Loop: active-links chip freshness
|
|
3077
|
+
// suffix wrapper picks up `tabular-nums` for digit
|
|
3078
|
+
// width-lock. Pre-R357 the literal "last {rel}"
|
|
3079
|
+
// text (e.g. "last 5s ago", "last 10s ago",
|
|
3080
|
+
// "last 1m ago") had natural-figure digits — the
|
|
3081
|
+
// freshness ticker updates every second, so the
|
|
3082
|
+
// 9→10 boundary on the seconds counter and the
|
|
3083
|
+
// 59→60s → 1m flip both jittered ~1-2 px of glyph
|
|
3084
|
+
// width which propagated through the chip-row's
|
|
3085
|
+
// inline-flex layout, nudging the freshness DOT
|
|
3086
|
+
// and the chip's left edge. Tabular-nums on the
|
|
3087
|
+
// wrapper applies to all descendant digits only
|
|
3088
|
+
// (letters render at natural widths) so the
|
|
3089
|
+
// ticker stays planted across every count cross.
|
|
3090
|
+
// Joins the R224-R232 info-density tabular-nums
|
|
3091
|
+
// sweep at the chip-row freshness scope. Pure
|
|
3092
|
+
// paint-level change, no geometry shift on rest.
|
|
3093
|
+
// The R342 text-gray-400 lift + R161 dot freshness
|
|
3094
|
+
// alpha ramp + R317 subordinate-text-lift family
|
|
3095
|
+
// all preserved. data-active-links-freshness-
|
|
3096
|
+
// wrapper attr exposes the wrapper for tests.
|
|
3097
|
+
<span className="text-gray-400 tabular-nums" data-active-links-freshness-wrapper>
|
|
2920
3098
|
<span
|
|
2921
3099
|
data-active-links-freshness-dot
|
|
2922
3100
|
data-active-links-freshness-alpha={alpha.toFixed(2)}
|
|
@@ -6213,7 +6391,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6213
6391
|
x="0" y="0" width="230" height="88" rx="10"
|
|
6214
6392
|
fill={pal.legendBox.fill}
|
|
6215
6393
|
stroke={pal.legendBox.stroke}
|
|
6216
|
-
|
|
6394
|
+
// Round 348 / Loop: recent-signal panel rect opacity hover-
|
|
6395
|
+
// state bump — joins the panel-hover cue stack (R135 drop-
|
|
6396
|
+
// shadow boost + R345 title letter-spacing tween 0.3 → 0.4
|
|
6397
|
+
// + R266 fill theme-flip). Cyber 0.92 → 0.97, light 0.97 →
|
|
6398
|
+
// 1.0 on hoveredPanel === 'recent'. The panel "solidifies"
|
|
6399
|
+
// on hover — pure paint-level change, geometry-safe (bbox
|
|
6400
|
+
// unchanged so topo-overlap-test invariants hold). The
|
|
6401
|
+
// R247 transition list already includes `opacity 200ms
|
|
6402
|
+
// ease-out` so the value tween is automatic. Sibling
|
|
6403
|
+
// change at legend panel rect below (~line 7222).
|
|
6404
|
+
opacity={hoveredPanel === 'recent' ? (isLight ? 1 : 0.97) : (isLight ? 0.97 : 0.92)}
|
|
6217
6405
|
style={{
|
|
6218
6406
|
/* R135: drop-shadow intensifies on panel hover. Base
|
|
6219
6407
|
shadow (2px / 6px blur) signals card elevation
|
|
@@ -6265,7 +6453,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6265
6453
|
title (line ~6556) — both panels share the same
|
|
6266
6454
|
editorial-text-spacing convention. data-recent-panel-
|
|
6267
6455
|
title handle unchanged so R266 test still resolves. */}
|
|
6268
|
-
|
|
6456
|
+
{/* Round 345 / Loop: recent-signal panel title gains
|
|
6457
|
+
letter-spacing tween 0.3 → 0.4 on panel hover.
|
|
6458
|
+
hoveredPanel === 'recent' is set by the panel <g>
|
|
6459
|
+
wrapper's onMouseEnter (line ~6263 area). Sibling to
|
|
6460
|
+
R344 hover-letter-spacing applied to the +N more
|
|
6461
|
+
flows footer — same gesture vocabulary at a panel-
|
|
6462
|
+
title scope: hovering the panel chrome spreads the
|
|
6463
|
+
title 0.1 px, signalling "this is a coherent unit
|
|
6464
|
+
you're entering". transition list extends letter-
|
|
6465
|
+
spacing 200ms ease-out alongside existing fill 200ms. */}
|
|
6466
|
+
<text x="13" y="21" fill={pal.legendHeadline} fontSize="12" fontFamily="monospace" fontWeight="700" letterSpacing={hoveredPanel === 'recent' ? '0.4' : '0.3'} style={{ transition: 'fill 200ms ease-out, letter-spacing 200ms ease-out' }} data-recent-panel-title>recent signal</text>
|
|
6269
6467
|
{/* R96: header count now matches what the rows show. Pre-R96
|
|
6270
6468
|
this read "X msgs" off the raw messages array, but the
|
|
6271
6469
|
rows below render DEDUPED flowLinks — so a fleet with 10
|
|
@@ -6326,8 +6524,8 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6326
6524
|
const alpha = ageSec <= 30
|
|
6327
6525
|
? 1
|
|
6328
6526
|
: ageSec <= 300
|
|
6329
|
-
? 1 - ((ageSec - 30) / 270) * 0.
|
|
6330
|
-
: 0.25
|
|
6527
|
+
? 1 - ((ageSec - 30) / 270) * 0.70 /* R358: floor 0.25 → 0.30 lift across 3 freshness scopes */
|
|
6528
|
+
: 0.30; /* R358: stale floor lifted 0.25 → 0.30 — 20% legibility bump while preserving fresh/stale ratio */
|
|
6331
6529
|
// Dark cyan-400 / light teal-600 with alpha — same
|
|
6332
6530
|
// palette as R161's chip bullet so the two scopes
|
|
6333
6531
|
// visually align even side-by-side.
|
|
@@ -6340,6 +6538,21 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6340
6538
|
textAnchor="end"
|
|
6341
6539
|
fontSize="10"
|
|
6342
6540
|
fontFamily="monospace"
|
|
6541
|
+
// Round 349 / Loop: editorial letter-spacing 0.2 on the
|
|
6542
|
+
// recent-signal panel header count. Sits one tier below
|
|
6543
|
+
// the R301 panel title letterSpacing="0.3" so the panel
|
|
6544
|
+
// header reads as a 2-step hierarchy (title 0.3 / count
|
|
6545
|
+
// 0.2). Sibling change on the legend panel count below
|
|
6546
|
+
// closes the panel-pair editorial symmetry. Joins the
|
|
6547
|
+
// R285 / R289 / R301 / R302 / R304 / R325 editorial-
|
|
6548
|
+
// letterspacing tier at the panel-summary scope. The
|
|
6549
|
+
// R162 freshness fill, R225 tabular-nums, R311 fw=600,
|
|
6550
|
+
// R336 unit-tspan opacity-0.7 split all preserved —
|
|
6551
|
+
// the tier propagates to all descendant tspans via
|
|
6552
|
+
// SVG inheritance. data-recent-panel-count-letter-
|
|
6553
|
+
// spacing exposes the value for tests.
|
|
6554
|
+
letterSpacing="0.2"
|
|
6555
|
+
data-recent-panel-count-letter-spacing="0.2"
|
|
6343
6556
|
>
|
|
6344
6557
|
{/* Round 225 / Loop: tabular-nums on the panel-header
|
|
6345
6558
|
flow-count tspan. The "{N} flows" string lives in
|
|
@@ -6808,17 +7021,38 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6808
7021
|
const alpha = ageSec <= 30
|
|
6809
7022
|
? 1
|
|
6810
7023
|
: ageSec <= 300
|
|
6811
|
-
? 1 - ((ageSec - 30) / 270) * 0.
|
|
6812
|
-
: 0.25
|
|
7024
|
+
? 1 - ((ageSec - 30) / 270) * 0.70 /* R358: floor 0.25 → 0.30 lift across 3 freshness scopes */
|
|
7025
|
+
: 0.30; /* R358: stale floor lifted 0.25 → 0.30 — 20% legibility bump while preserving fresh/stale ratio */
|
|
6813
7026
|
return (
|
|
6814
7027
|
<circle
|
|
6815
7028
|
cx={10}
|
|
6816
7029
|
cy={38 + index * 16 - 3}
|
|
6817
|
-
|
|
7030
|
+
/* Round 359 / Loop: recency pip base radius
|
|
7031
|
+
1.6 → 1.8. Sibling lift to R358's freshness-
|
|
7032
|
+
floor bump (alpha 0.25 → 0.30) — pre-R358/
|
|
7033
|
+
R359 the stale pip painted at r=1.6 + α=0.25
|
|
7034
|
+
which read as near-invisible chrome. R358
|
|
7035
|
+
gave it more alpha; R359 gives it more area
|
|
7036
|
+
(1.8² / 1.6² ≈ 1.27, so ~27 % more glyph)
|
|
7037
|
+
so the pip stays distinguishable across the
|
|
7038
|
+
freshness ramp. Geometry: 1.8-radius dot
|
|
7039
|
+
centred at (10, row_y - 3) is bbox 3.6×3.6,
|
|
7040
|
+
still well inside the 7-px left margin
|
|
7041
|
+
(x=6 rect-start → x=13 text-start) the R160
|
|
7042
|
+
pip was placed in. Overlap-test reads the
|
|
7043
|
+
parent row rect's bbox, not this pip's, so
|
|
7044
|
+
grid+ring invariants hold. Matches the same
|
|
7045
|
+
1.6 → 1.8 visual-weight bump R295 applied
|
|
7046
|
+
to the legend swatch (5.5 → 6 base radius)
|
|
7047
|
+
and R287 to the minimap viewport stroke
|
|
7048
|
+
(1 → 1.5). data-recent-row-freshness-radius
|
|
7049
|
+
attr exposes the value for tests. */
|
|
7050
|
+
r={1.8}
|
|
6818
7051
|
fill={pal.legendAccent}
|
|
6819
7052
|
opacity={alpha}
|
|
6820
7053
|
data-recent-row-freshness={link.key}
|
|
6821
7054
|
data-recent-row-freshness-alpha={alpha.toFixed(2)}
|
|
7055
|
+
data-recent-row-freshness-radius="1.8"
|
|
6822
7056
|
style={{ pointerEvents: 'none', transition: 'opacity 200ms ease-out' }}
|
|
6823
7057
|
/>
|
|
6824
7058
|
);
|
|
@@ -7100,6 +7334,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
7100
7334
|
preserved for the <title> tooltip — only the SVG
|
|
7101
7335
|
render splits. data-recent-panel-more-unit exposes
|
|
7102
7336
|
the unit tspan for tests. */}
|
|
7337
|
+
{/* Round 344 / Loop: footer hover gains letter-spacing
|
|
7338
|
+
tween 0.2 → 0.3. R325 set rest letter-spacing
|
|
7339
|
+
0.2 to join the editorial-spacing family; R344
|
|
7340
|
+
adds a 0.1px hover spread that layers on top of
|
|
7341
|
+
R195 cyan fill + R325 spacing + R133 underline
|
|
7342
|
+
so the footer reads "lit up and spaced" on
|
|
7343
|
+
hover — sibling to R218/R219/R220 pin-signature
|
|
7344
|
+
letter-spacing family applied to a hover-only
|
|
7345
|
+
surface. transition list extends letter-spacing
|
|
7346
|
+
200ms ease-out alongside the existing opacity/
|
|
7347
|
+
fill easings. */}
|
|
7103
7348
|
<text
|
|
7104
7349
|
x="115" y="82"
|
|
7105
7350
|
textAnchor="middle"
|
|
@@ -7107,12 +7352,12 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
7107
7352
|
fontSize="9"
|
|
7108
7353
|
fontFamily="monospace"
|
|
7109
7354
|
fontStyle="italic"
|
|
7110
|
-
letterSpacing=
|
|
7355
|
+
letterSpacing={hoveredRecentMore ? '0.3' : '0.2'}
|
|
7111
7356
|
opacity={hoveredRecentMore ? 0.85 : 0.55}
|
|
7112
7357
|
textDecoration={hoveredRecentMore ? 'underline' : 'none'}
|
|
7113
7358
|
data-recent-panel-more={moreCount}
|
|
7114
7359
|
data-recent-panel-more-hovered={hoveredRecentMore ? 'true' : 'false'}
|
|
7115
|
-
style={{ transition: 'opacity 150ms ease-out, fill 200ms ease-out' }}
|
|
7360
|
+
style={{ transition: 'opacity 150ms ease-out, fill 200ms ease-out, letter-spacing 200ms ease-out' }}
|
|
7116
7361
|
>
|
|
7117
7362
|
{`+ ${moreCount}`}
|
|
7118
7363
|
<tspan opacity="0.7" data-recent-panel-more-unit>{` more flow${moreCount === 1 ? '' : 's'}`}</tspan>
|
|
@@ -7164,7 +7409,12 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
7164
7409
|
x="0" y="0" width="224" height="88" rx="10"
|
|
7165
7410
|
fill={pal.legendBox.fill}
|
|
7166
7411
|
stroke={pal.legendBox.stroke}
|
|
7167
|
-
|
|
7412
|
+
// R348 sibling — legend panel rect opacity hover-state
|
|
7413
|
+
// bump 0.92 → 0.97 (cyber) / 0.97 → 1 (light) on
|
|
7414
|
+
// hoveredPanel === 'legend'. Pairs with the recent-signal
|
|
7415
|
+
// panel rect above so the two corner panels' hover cues
|
|
7416
|
+
// stay symmetric. Geometry-safe (paint-only).
|
|
7417
|
+
opacity={hoveredPanel === 'legend' ? (isLight ? 1 : 0.97) : (isLight ? 0.97 : 0.92)}
|
|
7168
7418
|
style={{
|
|
7169
7419
|
filter: hoveredPanel === 'legend'
|
|
7170
7420
|
? (isLight ? 'drop-shadow(0 4px 12px rgba(15,23,42,0.14))'
|
|
@@ -7187,7 +7437,9 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
7187
7437
|
surrounding chrome eased; R266 closes both at once. */}
|
|
7188
7438
|
{/* R301: sibling to recent-signal panel title above —
|
|
7189
7439
|
same letterSpacing 0.3 for editorial parity. */}
|
|
7190
|
-
|
|
7440
|
+
{/* R345 sibling — legend panel title same hover letter-
|
|
7441
|
+
spacing tween 0.3 → 0.4 on panel hover. */}
|
|
7442
|
+
<text x="13" y="21" fill={pal.legendHeadline} fontSize="12" fontFamily="monospace" fontWeight="700" letterSpacing={hoveredPanel === 'legend' ? '0.4' : '0.3'} style={{ transition: 'fill 200ms ease-out, letter-spacing 200ms ease-out' }} data-legend-panel-title>legend</text>
|
|
7191
7443
|
{/* Round 257 / Loop: legend panel header count picks up the
|
|
7192
7444
|
symmetric 13L/13R inner-padding pattern from the recent-
|
|
7193
7445
|
signal panel. Pre-R257 the legend header was 13px from
|
|
@@ -7251,7 +7503,14 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
7251
7503
|
<text
|
|
7252
7504
|
x="211" y="21" textAnchor="end"
|
|
7253
7505
|
fill={pal.legendAccent} fontSize="10" fontFamily="monospace" fontWeight="600"
|
|
7506
|
+
// R349 sibling — legend panel header count picks up
|
|
7507
|
+
// letterSpacing="0.2", one tier below the R301 panel
|
|
7508
|
+
// title 0.3. Pairs with the recent-signal panel count
|
|
7509
|
+
// letter-spacing above so the two corner panels' header
|
|
7510
|
+
// typography stays editorially symmetric.
|
|
7511
|
+
letterSpacing="0.2"
|
|
7254
7512
|
data-legend-panel-count
|
|
7513
|
+
data-legend-panel-count-letter-spacing="0.2"
|
|
7255
7514
|
style={{
|
|
7256
7515
|
transition: 'fill 200ms ease-out',
|
|
7257
7516
|
fontVariantNumeric: 'tabular-nums',
|
|
@@ -7793,7 +8052,13 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
7793
8052
|
resetView();
|
|
7794
8053
|
}
|
|
7795
8054
|
}}
|
|
8055
|
+
// R346: viewport rect hover affordance driven by parent.
|
|
8056
|
+
onMouseEnter={() => setHoveredMinimap(true)}
|
|
8057
|
+
onMouseLeave={() => setHoveredMinimap(false)}
|
|
8058
|
+
onFocus={() => setHoveredMinimap(true)}
|
|
8059
|
+
onBlur={() => setHoveredMinimap(false)}
|
|
7796
8060
|
data-topo-minimap
|
|
8061
|
+
data-topo-minimap-hovered={hoveredMinimap ? 'true' : 'false'}
|
|
7797
8062
|
>
|
|
7798
8063
|
<svg width={MW} height={MH} viewBox={`0 0 ${MW} ${MH}`} style={{ display: 'block' }}>
|
|
7799
8064
|
{/* Round 198 / Loop: minimap dots gain smooth status
|
|
@@ -7872,13 +8137,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
7872
8137
|
x={Math.max(0, rectX)} y={Math.max(0, rectY)}
|
|
7873
8138
|
width={Math.max(0, Math.min(MW - Math.max(0, rectX), rectW))}
|
|
7874
8139
|
height={Math.max(0, Math.min(MH - Math.max(0, rectY), rectH))}
|
|
7875
|
-
fill="none" stroke={pal.legendAccent}
|
|
8140
|
+
fill="none" stroke={pal.legendAccent}
|
|
8141
|
+
// R346: strokeWidth + opacity tween on container hover.
|
|
8142
|
+
strokeWidth={hoveredMinimap ? '1.75' : '1.5'}
|
|
8143
|
+
opacity={hoveredMinimap ? '1' : '0.9'}
|
|
7876
8144
|
data-topo-minimap-viewport
|
|
7877
8145
|
data-topo-minimap-viewport-smooth={smoothView ? 'true' : 'false'}
|
|
8146
|
+
data-topo-minimap-viewport-hover={hoveredMinimap ? 'true' : 'false'}
|
|
7878
8147
|
style={{
|
|
7879
8148
|
transition: smoothView
|
|
7880
|
-
? 'x 280ms ease-out, y 280ms ease-out, width 280ms ease-out, height 280ms ease-out'
|
|
7881
|
-
: '
|
|
8149
|
+
? 'x 280ms ease-out, y 280ms ease-out, width 280ms ease-out, height 280ms ease-out, stroke-width 200ms ease-out, opacity 200ms ease-out'
|
|
8150
|
+
: 'stroke-width 200ms ease-out, opacity 200ms ease-out',
|
|
7882
8151
|
} as React.CSSProperties}
|
|
7883
8152
|
/>
|
|
7884
8153
|
</svg>
|
|
@@ -8031,7 +8300,8 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8031
8300
|
// R196: press-state deepens bg one tier above hover (white/5
|
|
8032
8301
|
// → white/10) so mouse-down has a tactile dim before the
|
|
8033
8302
|
// R186 icon pop fires on release.
|
|
8034
|
-
|
|
8303
|
+
// R352: `group` lets the inner svg respond via group-hover.
|
|
8304
|
+
className="group px-2 py-1 hover:bg-white/5 active:bg-white/10 transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 focus-visible:ring-inset"
|
|
8035
8305
|
style={{ color: pal.legendText }}
|
|
8036
8306
|
aria-label="Zoom out"
|
|
8037
8307
|
title="Zoom out (−)"
|
|
@@ -8039,11 +8309,25 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8039
8309
|
{/* R186: icon pop on click. CSS animation runs once;
|
|
8040
8310
|
React removes the class after 240ms so a quick
|
|
8041
8311
|
re-click can replay. */}
|
|
8312
|
+
{/* Round 352 / Loop: zoom-out icon picks up group-hover:
|
|
8313
|
+
scale-110 — sibling to R350 reset hover-rotate. Pre-
|
|
8314
|
+
R352 hovering the zoom button only changed the bg
|
|
8315
|
+
(white/5); the icon inside stayed perfectly still.
|
|
8316
|
+
R352 lifts the icon 10% on hover for a tactile "this
|
|
8317
|
+
button does something" cue. The R186 anet-chrome-pop
|
|
8318
|
+
keyframe (220ms scale 1→1.06→1) still owns transform
|
|
8319
|
+
during click via CSS-animation precedence over
|
|
8320
|
+
transition-transform; after the pop ends + className
|
|
8321
|
+
is removed, the group-hover scale-110 picks up
|
|
8322
|
+
smoothly. `transform-gpu` hint promotes the svg to
|
|
8323
|
+
its own compositor layer for crisper edges during
|
|
8324
|
+
the scale tween. Sibling change on zoom-in icon
|
|
8325
|
+
below. */}
|
|
8042
8326
|
<svg
|
|
8043
8327
|
width="12" height="12" viewBox="0 0 24 24"
|
|
8044
8328
|
fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"
|
|
8045
8329
|
aria-hidden
|
|
8046
|
-
className={chromePopping === 'zoom-out' ? 'anet-chrome-pop' :
|
|
8330
|
+
className={`transition-transform duration-200 ease-out group-hover:scale-110 transform-gpu${chromePopping === 'zoom-out' ? ' anet-chrome-pop' : ''}`}
|
|
8047
8331
|
data-topo-chrome-zoom-out-icon
|
|
8048
8332
|
><path d="M5 12h14" /></svg>
|
|
8049
8333
|
</button>
|
|
@@ -8089,11 +8373,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8089
8373
|
chromePopping === 'zoom-in' || chromePopping === 'zoom-out'
|
|
8090
8374
|
? 'true' : 'false'
|
|
8091
8375
|
}
|
|
8376
|
+
data-topo-chrome-zoom-level-hover={hoveredZoomLevel ? 'true' : 'false'}
|
|
8377
|
+
onMouseEnter={() => setHoveredZoomLevel(true)}
|
|
8378
|
+
onMouseLeave={() => setHoveredZoomLevel(false)}
|
|
8092
8379
|
style={{
|
|
8093
8380
|
color: pal.legendText,
|
|
8094
8381
|
borderColor: pal.containerBorder,
|
|
8095
8382
|
minWidth: 46,
|
|
8096
8383
|
display: 'inline-block',
|
|
8384
|
+
// R347: letter-spacing hover tween — extends R344/R345
|
|
8385
|
+
// hover-letter-spacing family into the chrome strip.
|
|
8386
|
+
letterSpacing: hoveredZoomLevel ? '0.5px' : '0',
|
|
8097
8387
|
/* Round 264 / Loop: zoom level readout gains theme-toggle
|
|
8098
8388
|
transition. The span has theme-driven color (pal.
|
|
8099
8389
|
legendText) + border-x (pal.containerBorder via the
|
|
@@ -8102,7 +8392,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8102
8392
|
on theme flip while siblings eased. Sibling treatment
|
|
8103
8393
|
to the nodeSize + zoom wrapper transitions added this
|
|
8104
8394
|
round. */
|
|
8105
|
-
transition: 'color 200ms ease-out, border-color 200ms ease-out',
|
|
8395
|
+
transition: 'color 200ms ease-out, border-color 200ms ease-out, letter-spacing 200ms ease-out',
|
|
8106
8396
|
}}
|
|
8107
8397
|
title="Current zoom level"
|
|
8108
8398
|
>
|
|
@@ -8113,18 +8403,22 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8113
8403
|
data-topo-chrome-zoom-in
|
|
8114
8404
|
data-topo-chrome-zoom-in-popping={chromePopping === 'zoom-in' ? 'true' : 'false'}
|
|
8115
8405
|
// R196: press-state (mirror of zoom-out above).
|
|
8116
|
-
|
|
8406
|
+
// R352: `group` lets the inner svg respond via group-hover.
|
|
8407
|
+
className="group px-2 py-1 hover:bg-white/5 active:bg-white/10 transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 focus-visible:ring-inset"
|
|
8117
8408
|
style={{ color: pal.legendText }}
|
|
8118
8409
|
aria-label="Zoom in"
|
|
8119
8410
|
title="Zoom in (+)"
|
|
8120
8411
|
>
|
|
8121
8412
|
{/* R186: icon pop on click. Same one-shot CSS animation
|
|
8122
8413
|
as zoom-out; React removes the class after 240ms. */}
|
|
8414
|
+
{/* R352 sibling — zoom-in icon picks up the same
|
|
8415
|
+
group-hover:scale-110 family. Mirror change at
|
|
8416
|
+
the zoom-out icon above. */}
|
|
8123
8417
|
<svg
|
|
8124
8418
|
width="12" height="12" viewBox="0 0 24 24"
|
|
8125
8419
|
fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"
|
|
8126
8420
|
aria-hidden
|
|
8127
|
-
className={chromePopping === 'zoom-in' ? 'anet-chrome-pop' :
|
|
8421
|
+
className={`transition-transform duration-200 ease-out group-hover:scale-110 transform-gpu${chromePopping === 'zoom-in' ? ' anet-chrome-pop' : ''}`}
|
|
8128
8422
|
data-topo-chrome-zoom-in-icon
|
|
8129
8423
|
><path d="M12 5v14M5 12h14" /></svg>
|
|
8130
8424
|
</button>
|
|
@@ -8133,6 +8427,12 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8133
8427
|
onClick={() => { armResetSpin(); resetView(); }}
|
|
8134
8428
|
data-topo-chrome-reset
|
|
8135
8429
|
data-topo-chrome-reset-spinning={resetSpinning ? 'true' : 'false'}
|
|
8430
|
+
data-topo-chrome-reset-hover={hoveredReset ? 'true' : 'false'}
|
|
8431
|
+
// R350: hover state drives the icon transform below.
|
|
8432
|
+
onMouseEnter={() => setHoveredReset(true)}
|
|
8433
|
+
onMouseLeave={() => setHoveredReset(false)}
|
|
8434
|
+
onFocus={() => setHoveredReset(true)}
|
|
8435
|
+
onBlur={() => setHoveredReset(false)}
|
|
8136
8436
|
// R196: press-state deepens before R184 reset-spin fires on
|
|
8137
8437
|
// release — mouse-down dim then 450ms spin = full handshake.
|
|
8138
8438
|
className="p-1.5 rounded-md border hover:bg-white/5 active:bg-white/10 transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60"
|
|
@@ -8162,6 +8462,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8162
8462
|
aria-hidden
|
|
8163
8463
|
className={resetSpinning ? 'anet-reset-spin' : undefined}
|
|
8164
8464
|
data-topo-chrome-reset-icon
|
|
8465
|
+
// R350: hover-rotate preview of the R184 click-spin.
|
|
8466
|
+
// Gated on !resetSpinning so the anet-reset-spin keyframe
|
|
8467
|
+
// owns transform during its 450ms run. transformOrigin
|
|
8468
|
+
// 'center' so rotation pivots around the icon's centre
|
|
8469
|
+
// (default would be top-left and the icon would arc).
|
|
8470
|
+
style={{
|
|
8471
|
+
transform: hoveredReset && !resetSpinning ? 'rotate(-8deg)' : 'rotate(0deg)',
|
|
8472
|
+
transformOrigin: 'center',
|
|
8473
|
+
transition: 'transform 200ms ease-out',
|
|
8474
|
+
}}
|
|
8475
|
+
data-topo-chrome-reset-icon-hover={hoveredReset && !resetSpinning ? 'true' : 'false'}
|
|
8165
8476
|
>
|
|
8166
8477
|
<path d="M3 12a9 9 0 1 0 9-9 9 9 0 0 0-6.4 2.6L3 8" />
|
|
8167
8478
|
<path d="M3 3v5h5" />
|
|
@@ -8195,7 +8506,12 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8195
8506
|
its inactive state benefits from the same "hover previews
|
|
8196
8507
|
active state" idiom R163 designed. Sibling treatment to
|
|
8197
8508
|
the nodeSize buttons at line ~6711. */
|
|
8198
|
-
|
|
8509
|
+
// R353: `group` lets the inner svg respond via group-hover —
|
|
8510
|
+
// sibling to R352 zoom buttons. Closes the chrome-strip per-
|
|
8511
|
+
// icon hover-affordance arc (zoom-out / zoom-in / reset /
|
|
8512
|
+
// fullscreen now all carry an icon-level hover gesture in
|
|
8513
|
+
// addition to the bg hover).
|
|
8514
|
+
className={`group p-1.5 rounded-md border transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 ${
|
|
8199
8515
|
isFullscreen
|
|
8200
8516
|
? 'bg-cyan-500/15 text-cyan-300 font-medium hover:bg-cyan-500/20 active:bg-cyan-500/25'
|
|
8201
8517
|
: 'hover:bg-cyan-500/5 active:bg-cyan-500/15'
|
|
@@ -8214,12 +8530,20 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
8214
8530
|
at the reset icon above. data-topo-chrome-fullscreen-
|
|
8215
8531
|
icon attribute exposes BOTH variants (entered / exited)
|
|
8216
8532
|
for the round's stroke-width regression probe. */}
|
|
8533
|
+
{/* Round 353 / Loop: fullscreen icon (both enter + exit
|
|
8534
|
+
variants) picks up the R352 family group-hover:scale-110.
|
|
8535
|
+
Pre-R353 hovering the button only changed the bg; the
|
|
8536
|
+
icon stayed still. R353 lifts the icon 10 % on hover —
|
|
8537
|
+
same gesture vocabulary as the zoom buttons. transform-
|
|
8538
|
+
gpu hint promotes the svg to its own compositor layer
|
|
8539
|
+
for crisper edges during the scale tween. Closes the
|
|
8540
|
+
chrome-strip per-icon hover-affordance arc. */}
|
|
8217
8541
|
{isFullscreen ? (
|
|
8218
|
-
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden data-topo-chrome-fullscreen-icon="exit">
|
|
8542
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden className="transition-transform duration-200 ease-out group-hover:scale-110 transform-gpu" data-topo-chrome-fullscreen-icon="exit">
|
|
8219
8543
|
<path d="M8 3v4a1 1 0 0 1-1 1H3M21 8h-4a1 1 0 0 1-1-1V3M3 16h4a1 1 0 0 1 1 1v4M16 21v-4a1 1 0 0 1 1-1h4" />
|
|
8220
8544
|
</svg>
|
|
8221
8545
|
) : (
|
|
8222
|
-
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden data-topo-chrome-fullscreen-icon="enter">
|
|
8546
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden className="transition-transform duration-200 ease-out group-hover:scale-110 transform-gpu" data-topo-chrome-fullscreen-icon="enter">
|
|
8223
8547
|
<path d="M3 8V5a2 2 0 0 1 2-2h3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M21 16v3a2 2 0 0 1-2 2h-3" />
|
|
8224
8548
|
</svg>
|
|
8225
8549
|
)}
|