@sleep2agi/agent-network-dashboard 0.5.3-preview.1 → 0.5.3-preview.11
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 +7 -7
- 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/[root-of-the-server]__0sv~g.o._.js +1 -1
- package/.next/server/chunks/ssr/[root-of-the-server]__0sv~g.o._.js.map +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/03tmeg87bxqs3.js +4 -0
- package/.next/static/chunks/{0ce~u5hn~wege.js → 06kqj2vd..gul.js} +1 -1
- package/.next/static/chunks/09t2h9c0b1xjg.js +1 -0
- package/.next/static/chunks/0m.1mvl~t.avc.css +2 -0
- package/.next/static/chunks/0x3fl360u~cjf.js +1 -0
- package/.next/trace +2 -2
- package/.next/trace-build +1 -1
- package/app/components/TopoGraph.tsx +161 -21
- package/app/globals.css +91 -6
- package/package.json +1 -1
- package/scripts/topo-chip-row-press-test.mjs +93 -0
- package/scripts/topo-chrome-press-fullstrip-test.mjs +105 -0
- package/scripts/topo-chrome-press-scale-test.mjs +100 -0
- package/scripts/topo-filter-pills-press-test.mjs +96 -0
- package/scripts/topo-focus-outline-transition-test.mjs +107 -0
- package/scripts/topo-hover-ring-duration-test.mjs +87 -0
- package/scripts/topo-hub-idle-breath-test.mjs +104 -0
- package/scripts/topo-recent-hot-pulse-test.mjs +102 -0
- package/scripts/topo-svg-focus-transition-test.mjs +105 -0
- package/scripts/topo-vendor-activelinks-press-test.mjs +100 -0
- package/.next/static/chunks/0a4hmfvj-81x5.css +0 -2
- package/.next/static/chunks/14m8prv3qgm45.js +0 -4
- package/.next/static/chunks/17fq.aa.hsdd..js +0 -1
- package/.next/static/chunks/17~las5t-t.kj.js +0 -1
- /package/.next/static/{cBZM18sgaGtUo-xccD_a3 → hbG6dNDvul_c04Di9Ydwt}/_buildManifest.js +0 -0
- /package/.next/static/{cBZM18sgaGtUo-xccD_a3 → hbG6dNDvul_c04Di9Ydwt}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{cBZM18sgaGtUo-xccD_a3 → hbG6dNDvul_c04Di9Ydwt}/_ssgManifest.js +0 -0
|
@@ -1943,8 +1943,24 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
1943
1943
|
// doesn't list letter-spacing, so without this the
|
|
1944
1944
|
// hover:tracking-wide would snap. Sibling change on
|
|
1945
1945
|
// the Grid button below.
|
|
1946
|
-
|
|
1947
|
-
|
|
1946
|
+
// Round 492 / Loop — add `active:scale-95` press feedback
|
|
1947
|
+
// alongside R196's `active:bg-cyan-500/25` color-deepen.
|
|
1948
|
+
// Pre-R492 the chrome-strip Ring/Grid buttons had color
|
|
1949
|
+
// tactile (deeper cyan on mouse-down) + R249 chrome-pop
|
|
1950
|
+
// on release, but no transform during the press itself —
|
|
1951
|
+
// the button stayed planted between mouse-down and pop.
|
|
1952
|
+
// Adding `active:scale-95` (5% compression) on the
|
|
1953
|
+
// pressed pseudo-state, with `transform 150ms ease-out`
|
|
1954
|
+
// bundled into the inline transition list, gives haptic-
|
|
1955
|
+
// like push-back feedback. The press-down (down to 95%
|
|
1956
|
+
// scale) eases in over 150ms in sync with the bg/color
|
|
1957
|
+
// deepen; the release auto-springs back to scale-100 via
|
|
1958
|
+
// the same transition, then R249's anet-chrome-pop class
|
|
1959
|
+
// overlays the release-pop. Matching `transform-gpu`
|
|
1960
|
+
// promotes the layer so the scale doesn't trigger
|
|
1961
|
+
// layout/paint thrash. Sibling change on Grid below.
|
|
1962
|
+
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 active:scale-95 transform-gpu ${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' : ''}`}
|
|
1963
|
+
style={{ transition: 'background-color 150ms ease, color 150ms ease, letter-spacing 200ms ease-out, transform 150ms ease-out' }}
|
|
1948
1964
|
>
|
|
1949
1965
|
Ring
|
|
1950
1966
|
</button>
|
|
@@ -1963,7 +1979,10 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
1963
1979
|
// all chrome buttons.
|
|
1964
1980
|
// R351 sibling — Grid button picks up hover:tracking-wide
|
|
1965
1981
|
// + inline transition spec. Same vocabulary as Ring.
|
|
1966
|
-
|
|
1982
|
+
// R492 sibling — Grid button picks up active:scale-95
|
|
1983
|
+
// press feedback + transform in transition list. Same
|
|
1984
|
+
// vocabulary as Ring above.
|
|
1985
|
+
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 active:scale-95 transform-gpu ${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' : ''}`}
|
|
1967
1986
|
/* Round 268 / Loop: Grid button's left border (the
|
|
1968
1987
|
internal divider between Ring and Grid) picks up
|
|
1969
1988
|
pal.containerBorder, matching the wrapper change at
|
|
@@ -1973,8 +1992,10 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
1973
1992
|
transition list into the inline spec below so the
|
|
1974
1993
|
letter-spacing tween rides alongside without snapping
|
|
1975
1994
|
the border-color flip — border-color 200ms ease-out
|
|
1976
|
-
keeps R268's theme-toggle smoothness intact.
|
|
1977
|
-
|
|
1995
|
+
keeps R268's theme-toggle smoothness intact.
|
|
1996
|
+
R492 adds `transform 150ms ease-out` so active:scale-95
|
|
1997
|
+
eases smoothly. */
|
|
1998
|
+
style={{ borderColor: pal.containerBorder, transition: 'background-color 150ms ease, color 150ms ease, border-color 200ms ease-out, letter-spacing 200ms ease-out, transform 150ms ease-out' }}
|
|
1978
1999
|
>
|
|
1979
2000
|
Grid
|
|
1980
2001
|
</button>
|
|
@@ -2091,9 +2112,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2091
2112
|
// to R355 filter pin pill inner-span hover-brighten.
|
|
2092
2113
|
// Hover-brighten family extends from filter pills to
|
|
2093
2114
|
// chip-row chips at the inner-span scope.
|
|
2115
|
+
// Round 494 / Loop — chip-row working chip joins the
|
|
2116
|
+
// active:scale-95 press-feedback family (R492 Ring/Grid +
|
|
2117
|
+
// R493 chrome-strip rest). Gated on the clickable branch
|
|
2118
|
+
// (workingCount > 0) — when the chip is a placeholder
|
|
2119
|
+
// at count=0, scale-95 stays off to match the existing
|
|
2120
|
+
// R398 hover-lift conditional. Composes with hover:-
|
|
2121
|
+
// translate-y-px for the same lift-and-compress
|
|
2122
|
+
// tactile signature R493 brought to reset/fullscreen.
|
|
2094
2123
|
className={`group tabular-nums font-medium px-2.5 py-1 rounded-md border anet-topo-chip-focus transition-colors transition-transform duration-200 ease-out transform-gpu ${
|
|
2095
2124
|
workingCount > 0
|
|
2096
|
-
? 'bg-green-500/10 text-green-300 border-green-500/20 hover:bg-green-500/15 hover:border-green-500/30 hover:-translate-y-px'
|
|
2125
|
+
? 'bg-green-500/10 text-green-300 border-green-500/20 hover:bg-green-500/15 hover:border-green-500/30 hover:-translate-y-px active:scale-95'
|
|
2097
2126
|
: 'bg-green-500/10 text-green-300 border-green-500/20'
|
|
2098
2127
|
}`}
|
|
2099
2128
|
data-chip-hover-lift={workingCount > 0 ? 'true' : 'false'}
|
|
@@ -2193,9 +2222,12 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2193
2222
|
same digit-jitter physics on count crossings). */
|
|
2194
2223
|
// R398: hover translate-y lift on clickable variant — see working chip above.
|
|
2195
2224
|
// R414: `group` parent + inner unit span group-hover-brighten — see working chip above.
|
|
2225
|
+
// R494 sibling — online chip joins the active:scale-95 press
|
|
2226
|
+
// family (gated on onlineNodes.length > 0 clickable branch,
|
|
2227
|
+
// same conditional pattern as the working chip above).
|
|
2196
2228
|
className={`group tabular-nums font-medium px-2.5 py-1 rounded-md border anet-topo-chip-focus transition-colors transition-transform duration-200 ease-out transform-gpu ${
|
|
2197
2229
|
onlineNodes.length > 0
|
|
2198
|
-
? 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20 hover:bg-cyan-500/15 hover:border-cyan-500/30 hover:-translate-y-px'
|
|
2230
|
+
? 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20 hover:bg-cyan-500/15 hover:border-cyan-500/30 hover:-translate-y-px active:scale-95'
|
|
2199
2231
|
: 'bg-cyan-500/10 text-cyan-300 border-cyan-500/20'
|
|
2200
2232
|
}`}
|
|
2201
2233
|
data-chip-hover-lift={onlineNodes.length > 0 ? 'true' : 'false'}
|
|
@@ -2470,7 +2502,13 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2470
2502
|
// R355: `group` lets the inner opacity-70 spans (prefix
|
|
2471
2503
|
// `filter:` + count `· N`) brighten to 100 % on pill hover.
|
|
2472
2504
|
// Sibling treatment on group + vendor pills below.
|
|
2473
|
-
|
|
2505
|
+
// R495 — filter pills (3 sibling `group` variants) join the
|
|
2506
|
+
// active:scale-95 press-feedback family. R490's !important
|
|
2507
|
+
// transition list on .anet-topo-chip-focus already covers
|
|
2508
|
+
// transform, so just appending active:scale-95 to the
|
|
2509
|
+
// className wires the press tactile in one token. Compound
|
|
2510
|
+
// with R400-era hover:-translate-y-px gives lift-and-compress.
|
|
2511
|
+
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 transition-transform duration-200 ease-out hover:-translate-y-px active:scale-95 transform-gpu" data-topo-filter-pill-hover-lift="true"
|
|
2474
2512
|
title={matchCount > 0 ? `${matchPreview}${matchSuffix} — click to clear` : 'Click to clear filter'}
|
|
2475
2513
|
onClick={() => setPinnedStatus(null)}
|
|
2476
2514
|
style={{
|
|
@@ -2534,7 +2572,13 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2534
2572
|
data-filter-match-count={matchCount}
|
|
2535
2573
|
data-filter-match-aliases={matchAliases.join(',')}
|
|
2536
2574
|
// R355 sibling — `group` parent + group-hover on inner spans.
|
|
2537
|
-
|
|
2575
|
+
// R495 — filter pills (3 sibling `group` variants) join the
|
|
2576
|
+
// active:scale-95 press-feedback family. R490's !important
|
|
2577
|
+
// transition list on .anet-topo-chip-focus already covers
|
|
2578
|
+
// transform, so just appending active:scale-95 to the
|
|
2579
|
+
// className wires the press tactile in one token. Compound
|
|
2580
|
+
// with R400-era hover:-translate-y-px gives lift-and-compress.
|
|
2581
|
+
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 transition-transform duration-200 ease-out hover:-translate-y-px active:scale-95 transform-gpu" data-topo-filter-pill-hover-lift="true"
|
|
2538
2582
|
title={matchCount > 0 ? `${matchPreview}${matchSuffix} — click to clear` : 'Click to clear filter'}
|
|
2539
2583
|
onClick={() => setPinnedGroup(null)}
|
|
2540
2584
|
style={{
|
|
@@ -2600,7 +2644,13 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2600
2644
|
data-filter-match-count={matchCount}
|
|
2601
2645
|
data-filter-match-aliases={matchAliases.join(',')}
|
|
2602
2646
|
// R355 sibling — `group` parent + group-hover on inner spans.
|
|
2603
|
-
|
|
2647
|
+
// R495 — filter pills (3 sibling `group` variants) join the
|
|
2648
|
+
// active:scale-95 press-feedback family. R490's !important
|
|
2649
|
+
// transition list on .anet-topo-chip-focus already covers
|
|
2650
|
+
// transform, so just appending active:scale-95 to the
|
|
2651
|
+
// className wires the press tactile in one token. Compound
|
|
2652
|
+
// with R400-era hover:-translate-y-px gives lift-and-compress.
|
|
2653
|
+
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 transition-transform duration-200 ease-out hover:-translate-y-px active:scale-95 transform-gpu" data-topo-filter-pill-hover-lift="true"
|
|
2604
2654
|
title={matchCount > 0 ? `${matchPreview}${matchSuffix} — click to clear` : 'Click to clear vendor filter'}
|
|
2605
2655
|
onClick={() => setPinnedVendor(null)}
|
|
2606
2656
|
style={{
|
|
@@ -2663,7 +2713,10 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
2663
2713
|
data-filter-match-count={link.count}
|
|
2664
2714
|
data-filter-match-aliases={`${link.from},${link.to}`}
|
|
2665
2715
|
data-active-filter-edge-hot={isHot ? 'true' : 'false'}
|
|
2666
|
-
|
|
2716
|
+
// R495 sibling — 4th filter pill (no `group` prefix variant)
|
|
2717
|
+
// joins active:scale-95 press family alongside the 3 group
|
|
2718
|
+
// variants above. Same recipe.
|
|
2719
|
+
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 transition-transform duration-200 ease-out hover:-translate-y-px active:scale-95 transform-gpu" data-topo-filter-pill-hover-lift="true"
|
|
2667
2720
|
title={`${link.from} → ${link.to} (${link.count} msg${link.count === 1 ? '' : 's'}${isHot ? ', hot lane · ≥ 10' : ''}) — click to clear`}
|
|
2668
2721
|
onClick={() => setPinnedEdgeKey(null)}
|
|
2669
2722
|
style={{
|
|
@@ -3013,7 +3066,12 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3013
3066
|
// — sibling to R355 filter-pill prefix/suffix + R414
|
|
3014
3067
|
// chip-row unit brighten. Closes the inner-span
|
|
3015
3068
|
// hover-brighten family at the vendor chip surface.
|
|
3016
|
-
|
|
3069
|
+
// R496 — vendor letter chip joins active:scale-95 press
|
|
3070
|
+
// family. Last vendor-row clickable joining the family
|
|
3071
|
+
// R495 cashed via R490's transition-cascade dividend.
|
|
3072
|
+
// Same compound w/ R401 hover-lift idiom — lift-and-
|
|
3073
|
+
// compress on press, springs back on release.
|
|
3074
|
+
className="group tabular-nums font-medium inline-flex items-baseline gap-0.5 px-1 rounded anet-topo-chip-focus transition-transform duration-200 ease-out transform-gpu hover:-translate-y-px active:scale-95"
|
|
3017
3075
|
data-vendor-letter={v.initial}
|
|
3018
3076
|
data-vendor-letter-count={v.count}
|
|
3019
3077
|
data-vendor-letter-hover-lift="true"
|
|
@@ -3251,9 +3309,13 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
3251
3309
|
data-chip-hover-lift attr exposes the lift surface
|
|
3252
3310
|
state ('true' clickable, 'false' empty) for tests. */
|
|
3253
3311
|
// R414: `group` parent + inner unit span group-hover-brighten — see working chip above.
|
|
3312
|
+
// R496 — active-links chip joins active:scale-95 press
|
|
3313
|
+
// family. Sibling to working+online chips (R494). Gated
|
|
3314
|
+
// on `isInteractive` (flowLinks.length > 0) — same R399
|
|
3315
|
+
// conditional pattern used for hover-lift.
|
|
3254
3316
|
className={`group tabular-nums font-medium hidden sm:inline px-2.5 py-1 rounded-md border anet-topo-chip-focus transition-transform duration-200 ease-out transform-gpu ${
|
|
3255
3317
|
isInteractive
|
|
3256
|
-
? 'bg-gray-500/10 text-gray-400 border-gray-500/20 hover:bg-cyan-500/10 hover:text-cyan-200 hover:border-cyan-500/30 hover:-translate-y-px'
|
|
3318
|
+
? 'bg-gray-500/10 text-gray-400 border-gray-500/20 hover:bg-cyan-500/10 hover:text-cyan-200 hover:border-cyan-500/30 hover:-translate-y-px active:scale-95'
|
|
3257
3319
|
: 'bg-gray-500/10 text-gray-400 border-gray-500/20'
|
|
3258
3320
|
}`}
|
|
3259
3321
|
data-chip-hover-lift={isInteractive ? 'true' : 'false'}
|
|
@@ -6537,11 +6599,36 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6537
6599
|
data-topo-hub-highlight-visible={workingCount > 0 ? 'false' : 'true'}
|
|
6538
6600
|
data-topo-hub-highlight-radius="5.5"
|
|
6539
6601
|
data-topo-hub-highlight-opacity={workingCount > 0 ? 0 : 0.95}
|
|
6602
|
+
data-topo-hub-highlight-breath={!reducedMotion && workingCount === 0 ? 'true' : 'false'}
|
|
6540
6603
|
style={{
|
|
6541
6604
|
pointerEvents: 'none',
|
|
6542
6605
|
transition: 'opacity 300ms ease-out',
|
|
6543
6606
|
}}
|
|
6544
|
-
|
|
6607
|
+
>
|
|
6608
|
+
{/* Round 497 / Loop — idle-state breath (呼吸感 theme pivot
|
|
6609
|
+
from the R492-R496 press-family arc). Pre-R497 the hub
|
|
6610
|
+
idle highlight read as a static dim disc — present but
|
|
6611
|
+
motionless, visually mute. R497 adds a 4s opacity breath
|
|
6612
|
+
(0.85 ↔ 1.0 ↔ 0.85) so the hub reads "alive but quiet"
|
|
6613
|
+
instead of "frozen", giving the empty-fleet state a
|
|
6614
|
+
subtle living signature.
|
|
6615
|
+
Gates:
|
|
6616
|
+
- !reducedMotion (R29 a11y blanket) — reducedMotion
|
|
6617
|
+
users see static 0.95 disc, no animate
|
|
6618
|
+
- workingCount === 0 — when fleet is busy, the
|
|
6619
|
+
highlight is invisible (opacity=0) so the animate
|
|
6620
|
+
would waste paint cycles. Gating saves work.
|
|
6621
|
+
SMIL <animate> overrides the static opacity={0.95}
|
|
6622
|
+
during its run; falls back to 0.95 when reducedMotion
|
|
6623
|
+
flips on (the animate node simply doesn't render).
|
|
6624
|
+
4s cycle is long enough to feel like ambient breath
|
|
6625
|
+
rather than a pulse, matching the "quiet" semantic.
|
|
6626
|
+
data-topo-hub-highlight-breath attr exposes the
|
|
6627
|
+
resolved gate state for tests. */}
|
|
6628
|
+
{!reducedMotion && workingCount === 0 && (
|
|
6629
|
+
<animate attributeName="opacity" values="0.85;1;0.85" dur="4s" repeatCount="indefinite" />
|
|
6630
|
+
)}
|
|
6631
|
+
</circle>
|
|
6545
6632
|
{/* R115 / Loop: hover hint ring. Stroke-only circle at r=14
|
|
6546
6633
|
that fades in when the hub is hovered — the same idea
|
|
6547
6634
|
R44 used for node avatars (group-hover stroke). r=14
|
|
@@ -6884,7 +6971,17 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6884
6971
|
in when the cursor enters the node, signalling clickability
|
|
6885
6972
|
(real-user feedback for the chat-popover open). Pure CSS via
|
|
6886
6973
|
Tailwind group-hover, so it costs nothing per frame and
|
|
6887
|
-
respects prefers-reduced-motion via the global media query.
|
|
6974
|
+
respects prefers-reduced-motion via the global media query.
|
|
6975
|
+
Round 489 / Loop — duration harmonized from 150ms → 200ms
|
|
6976
|
+
to join the Hero D #147 motion-coherence stack (R459-R475
|
|
6977
|
+
cluster surfaces + cadence-sync family). R2 originally
|
|
6978
|
+
picked 150ms for a "snappier feel" before the 200ms ease-
|
|
6979
|
+
out vocabulary was banked as the canvas-wide motion
|
|
6980
|
+
default. Bringing this ring into the family means hover-
|
|
6981
|
+
in / hover-out / cluster cadence / pip-strip transitions
|
|
6982
|
+
all settle on the same timing — the canvas now reads as
|
|
6983
|
+
one motion vocabulary instead of two competing tempos.
|
|
6984
|
+
11th surface in the motion-coherence stack. */}
|
|
6888
6985
|
<circle
|
|
6889
6986
|
cx={pos.x}
|
|
6890
6987
|
cy={pos.y}
|
|
@@ -6896,7 +6993,7 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
6896
6993
|
// exact widths and would mis-count this invisible hover
|
|
6897
6994
|
// ring as a node footprint.
|
|
6898
6995
|
strokeWidth="2"
|
|
6899
|
-
className="opacity-0 group-hover:opacity-70 transition-opacity duration-
|
|
6996
|
+
className="opacity-0 group-hover:opacity-70 transition-opacity duration-200"
|
|
6900
6997
|
style={{ pointerEvents: 'none' }}
|
|
6901
6998
|
/>
|
|
6902
6999
|
{/* Round 11 / Loop: chat-focus ring — when the ChatPopover is
|
|
@@ -9368,12 +9465,30 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
9368
9465
|
under the same R320 fill cadence. data-
|
|
9369
9466
|
recent-row-count-pinned attr exposes the
|
|
9370
9467
|
pin gate for tests. */}
|
|
9468
|
+
{/* Round 498 / Loop — hot-count subtle pulse. Pre-
|
|
9469
|
+
R498 the hot row count signaled via color (R127
|
|
9470
|
+
amber fill) + weight (R320 fw-700) + (R445 pin
|
|
9471
|
+
lift) but stayed visually motionless. R498 adds
|
|
9472
|
+
a 3s opacity breath (0.85↔1.0) on the digit when
|
|
9473
|
+
isHot && !reducedMotion — gentle "alive" signal
|
|
9474
|
+
on the lane carrying ≥ 10 messages, drawing
|
|
9475
|
+
glance without becoming noisy. Sibling of R497
|
|
9476
|
+
hub-idle-breath in the 呼吸感 theme arc; same
|
|
9477
|
+
0.85↔1.0 amplitude. Class adds an animation-
|
|
9478
|
+
only paint axis; no layout / bbox change. R29
|
|
9479
|
+
blanket also catches `animation-duration` for
|
|
9480
|
+
reducedMotion users, but the component-side
|
|
9481
|
+
gate makes the intent explicit and avoids
|
|
9482
|
+
a node tree thrash for those users (className
|
|
9483
|
+
stays absent rather than present-but-paused). */}
|
|
9371
9484
|
<tspan
|
|
9372
9485
|
fill={isHot ? hotStroke : undefined}
|
|
9373
9486
|
fontWeight={(isHot || isRowPinned) ? '700' : '600'}
|
|
9487
|
+
className={isHot && !reducedMotion ? 'anet-recent-hot-pulse' : undefined}
|
|
9374
9488
|
data-recent-row-count
|
|
9375
9489
|
data-recent-row-count-pinned={isRowPinned ? 'true' : 'false'}
|
|
9376
9490
|
data-recent-row-count-font-weight={(isHot || isRowPinned) ? '700' : '600'}
|
|
9491
|
+
data-recent-row-count-hot-pulse={isHot && !reducedMotion ? 'true' : 'false'}
|
|
9377
9492
|
{...(isHot ? { 'data-recent-row-count-hot': 'true' } : {})}
|
|
9378
9493
|
style={{
|
|
9379
9494
|
transition: 'fill 300ms ease-out, font-weight 200ms ease-out',
|
|
@@ -10957,7 +11072,15 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
10957
11072
|
/ fullscreen) preview their active state on hover.
|
|
10958
11073
|
Pure actions (zoom -/+, reset) stay white — they
|
|
10959
11074
|
aren't toggles, have no active state to preview. */
|
|
10960
|
-
|
|
11075
|
+
// Round 493 / Loop — extends R492 chrome-strip press-feedback
|
|
11076
|
+
// family to nodeSize S/M/L buttons. Adds active:scale-95
|
|
11077
|
+
// alongside the existing color-deepen (R196) + chrome-pop
|
|
11078
|
+
// (R249). transition-transform + duration-200 + ease-out
|
|
11079
|
+
// + transform-gpu added since this className previously had
|
|
11080
|
+
// transition-colors only — without the transform transition,
|
|
11081
|
+
// active:scale-95 would hard-cut. transform-gpu promotes the
|
|
11082
|
+
// layer so scale doesn't trigger paint thrash.
|
|
11083
|
+
className={`px-2 py-1 transition-colors transition-transform duration-200 ease-out transform-gpu active:scale-95 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 focus-visible:ring-inset ${idx > 0 ? 'border-l' : ''} ${nodeScale === v ? 'bg-cyan-500/15 text-cyan-300 font-medium hover:bg-cyan-500/20 active:bg-cyan-500/25' : 'hover:bg-cyan-500/5 active:bg-cyan-500/15'}${chromePopping === popKey ? ' anet-chrome-pop' : ''}`}
|
|
10961
11084
|
style={{ color: nodeScale === v ? undefined : pal.legendText, borderColor: pal.containerBorder }}
|
|
10962
11085
|
>
|
|
10963
11086
|
{lbl}
|
|
@@ -10999,7 +11122,11 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
10999
11122
|
// → white/10) so mouse-down has a tactile dim before the
|
|
11000
11123
|
// R186 icon pop fires on release.
|
|
11001
11124
|
// R352: `group` lets the inner svg respond via group-hover.
|
|
11002
|
-
|
|
11125
|
+
// R493 — zoom +/− buttons join the chrome-strip active:scale-95
|
|
11126
|
+
// press-feedback family (R492 + nodeSize above). transition-
|
|
11127
|
+
// transform + duration-200 + ease-out + transform-gpu added
|
|
11128
|
+
// since the className had only transition-colors.
|
|
11129
|
+
className="group px-2 py-1 hover:bg-white/5 active:bg-white/10 transition-colors transition-transform duration-200 ease-out transform-gpu active:scale-95 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 focus-visible:ring-inset"
|
|
11003
11130
|
style={{ color: pal.legendText }}
|
|
11004
11131
|
aria-label="Zoom out"
|
|
11005
11132
|
title="Zoom out (−)"
|
|
@@ -11139,7 +11266,11 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
11139
11266
|
data-topo-chrome-zoom-in-popping={chromePopping === 'zoom-in' ? 'true' : 'false'}
|
|
11140
11267
|
// R196: press-state (mirror of zoom-out above).
|
|
11141
11268
|
// R352: `group` lets the inner svg respond via group-hover.
|
|
11142
|
-
|
|
11269
|
+
// R493 — zoom +/− buttons join the chrome-strip active:scale-95
|
|
11270
|
+
// press-feedback family (R492 + nodeSize above). transition-
|
|
11271
|
+
// transform + duration-200 + ease-out + transform-gpu added
|
|
11272
|
+
// since the className had only transition-colors.
|
|
11273
|
+
className="group px-2 py-1 hover:bg-white/5 active:bg-white/10 transition-colors transition-transform duration-200 ease-out transform-gpu active:scale-95 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 focus-visible:ring-inset"
|
|
11143
11274
|
style={{ color: pal.legendText }}
|
|
11144
11275
|
aria-label="Zoom in"
|
|
11145
11276
|
title="Zoom in (+)"
|
|
@@ -11191,7 +11322,14 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
11191
11322
|
Every standalone interactive HTML surface in TopoGraph
|
|
11192
11323
|
now lifts on hover. data-topo-chrome-reset-hover-lift
|
|
11193
11324
|
attr surfaces the lift for tests. */
|
|
11194
|
-
|
|
11325
|
+
// R493 — reset button joins the chrome-strip active:scale-95
|
|
11326
|
+
// press-feedback family. The button already has transition-
|
|
11327
|
+
// transform + transform-gpu (R350 reset spin + R400 hover lift),
|
|
11328
|
+
// so just appending active:scale-95 plugs straight in. Compound
|
|
11329
|
+
// active state during press = hover-lift (-1px) + scale-95
|
|
11330
|
+
// composes as translateY(-1px) scale(0.95) — lift-and-compress
|
|
11331
|
+
// for tactile click feel.
|
|
11332
|
+
className="p-1.5 rounded-md border hover:bg-white/5 active:bg-white/10 hover:-translate-y-px active:scale-95 transition-colors transition-transform duration-200 ease-out transform-gpu focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60"
|
|
11195
11333
|
data-topo-chrome-reset-hover-lift="true"
|
|
11196
11334
|
style={{ background: pal.legendBox.fill, borderColor: pal.containerBorder, color: pal.legendText }}
|
|
11197
11335
|
aria-label="Reset view"
|
|
@@ -11284,7 +11422,9 @@ export function TopoGraph({ sessions, sseSessions, renameSignal }: TopoGraphProp
|
|
|
11284
11422
|
// fullscreen now all carry an icon-level hover gesture in
|
|
11285
11423
|
// addition to the bg hover).
|
|
11286
11424
|
// R400: hover translateY(-1px) lift — see reset button above for family doc.
|
|
11287
|
-
|
|
11425
|
+
// R493 — fullscreen joins active:scale-95 press family (same as
|
|
11426
|
+
// reset above: lift-and-compress compound transform on press).
|
|
11427
|
+
className={`group p-1.5 rounded-md border hover:-translate-y-px active:scale-95 transition-colors transition-transform duration-200 ease-out transform-gpu focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-400/60 ${
|
|
11288
11428
|
isFullscreen
|
|
11289
11429
|
? 'bg-cyan-500/15 text-cyan-300 font-medium hover:bg-cyan-500/20 active:bg-cyan-500/25'
|
|
11290
11430
|
: 'hover:bg-cyan-500/5 active:bg-cyan-500/15'
|
package/app/globals.css
CHANGED
|
@@ -863,6 +863,29 @@ body {
|
|
|
863
863
|
transform-box: fill-box;
|
|
864
864
|
}
|
|
865
865
|
|
|
866
|
+
/* Round 498 — recent-signal row hot-count subtle pulse (信息密度 +
|
|
867
|
+
呼吸感 themes). When a row's edge count crosses the hot threshold
|
|
868
|
+
(≥ 10), the existing R127/R320/R445 amber-fill + fw-700 typography
|
|
869
|
+
already calls attention; R498 adds a slow 3s opacity breath (0.85 ↔
|
|
870
|
+
1.0) on the digit so the hot tspans gently pulse — at-a-glance scan
|
|
871
|
+
of the panel reads "high-traffic lane right here" with motion in
|
|
872
|
+
addition to color+weight. 3s cycle is deliberate: faster (1-2s)
|
|
873
|
+
would compete with the working-status halo cadence; slower (5s+)
|
|
874
|
+
would lose the "alive" signal. Amplitude 15% (matches R497 hub-
|
|
875
|
+
highlight breath idiom).
|
|
876
|
+
prefers-reduced-motion handled by the R29 blanket override
|
|
877
|
+
(animation-duration: 0.001ms !important) — no per-class guard
|
|
878
|
+
needed. The component-side gate (`!reducedMotion && isHot`)
|
|
879
|
+
ensures the className is only applied when both conditions hold,
|
|
880
|
+
so even without the blanket the no-motion preference is respected. */
|
|
881
|
+
@keyframes anet-recent-hot-pulse-kf {
|
|
882
|
+
0%, 100% { opacity: 0.85; }
|
|
883
|
+
50% { opacity: 1; }
|
|
884
|
+
}
|
|
885
|
+
.anet-recent-hot-pulse {
|
|
886
|
+
animation: anet-recent-hot-pulse-kf 3s ease-in-out infinite;
|
|
887
|
+
}
|
|
888
|
+
|
|
866
889
|
/* Round 36 — current-step ring pulse on TaskDrawer timeline. Halo gently
|
|
867
890
|
breathes around the active step's dot so users can spot "task is here". */
|
|
868
891
|
@keyframes anet-current-step-pulse-kf {
|
|
@@ -900,10 +923,47 @@ body {
|
|
|
900
923
|
and doesn't fight box-shadow, so we use it here. `currentColor`
|
|
901
924
|
inherits the chip's own accent (green for working, cyan for online,
|
|
902
925
|
per-vendor for letters, etc.). Only fires on :focus-visible
|
|
903
|
-
(keyboard) — mouse focus stays unstyled.
|
|
904
|
-
|
|
905
|
-
|
|
926
|
+
(keyboard) — mouse focus stays unstyled.
|
|
927
|
+
Round 490 / Loop — focus outline transitions on color rather than
|
|
928
|
+
hard-cutting. Pre-R490 the keyboard focus ring snapped in/out
|
|
929
|
+
instantly (no `transition` declaration), while every other hover/
|
|
930
|
+
pin state on the same chip eased through the Hero D 200ms ease-out
|
|
931
|
+
vocabulary (R459-R475 cluster + R489 hover ring). Keyboard users
|
|
932
|
+
tabbing through chips saw discontinuous focus jumps — pointer
|
|
933
|
+
users saw smooth motion. R490 unifies the two by holding a
|
|
934
|
+
permanent transparent outline (no painted footprint, no layout
|
|
935
|
+
shift — `outline` is drawn outside the border-box and doesn't
|
|
936
|
+
trigger reflow) and transitioning ONLY outline-color when focus
|
|
937
|
+
arrives/leaves. The cyber-theme dark canvas keyboard nav now
|
|
938
|
+
reads as one motion vocabulary with pointer hover. */
|
|
939
|
+
.anet-topo-chip-focus {
|
|
940
|
+
outline: 2px solid transparent;
|
|
906
941
|
outline-offset: 1px;
|
|
942
|
+
/* R490 (revised) — Tailwind utility classes on the chips (transition-
|
|
943
|
+
colors / transition-transform / duration-200) set their own
|
|
944
|
+
`transition-property` list at the same selector specificity (0,1,0),
|
|
945
|
+
and since Tailwind's stylesheet loads after globals.css they win
|
|
946
|
+
the cascade — without `!important` my outline-color transition is
|
|
947
|
+
ignored. The unified list below replaces Tailwind's narrower list
|
|
948
|
+
with a superset (color, bg, border, opacity, box-shadow, transform
|
|
949
|
+
all preserved) plus `outline-color` for R490. All at 200ms ease-
|
|
950
|
+
out, matching the chip-row's existing Tailwind duration-200 ease-
|
|
951
|
+
out so visible animations on the chip are unchanged.
|
|
952
|
+
Trade-off: chips with inline `style.transition` (e.g. R210
|
|
953
|
+
pressure-bar segments at 220ms width / 150ms boxShadow / 150ms
|
|
954
|
+
filter, line 2338 in TopoGraph.tsx) keep their inline value
|
|
955
|
+
because inline style wins over class rules regardless of
|
|
956
|
+
!important. That's intentional — those custom timings were
|
|
957
|
+
deliberate and stay scoped to their element. */
|
|
958
|
+
transition-property:
|
|
959
|
+
outline-color, color, background-color, border-color,
|
|
960
|
+
text-decoration-color, fill, stroke, opacity, box-shadow, transform
|
|
961
|
+
!important;
|
|
962
|
+
transition-duration: 200ms !important;
|
|
963
|
+
transition-timing-function: ease-out !important;
|
|
964
|
+
}
|
|
965
|
+
.anet-topo-chip-focus:focus-visible {
|
|
966
|
+
outline-color: currentColor;
|
|
907
967
|
}
|
|
908
968
|
|
|
909
969
|
/* R156 — focus-visible outline for SVG-side TopoGraph interactives.
|
|
@@ -914,10 +974,35 @@ body {
|
|
|
914
974
|
R144/R151/R152). Browser default focus outline on SVG is hard
|
|
915
975
|
to spot against the canvas; explicit cyan-300 ring matches the
|
|
916
976
|
dashboard's legendAccent. 2-px outline-offset gives breathing
|
|
917
|
-
room around the painted bounding box.
|
|
918
|
-
|
|
919
|
-
|
|
977
|
+
room around the painted bounding box.
|
|
978
|
+
Round 491 / Loop — SVG-side counterpart to R490's chip-focus
|
|
979
|
+
outline-color transition. Pre-R491 keyboard focus on SVG g
|
|
980
|
+
elements (recent rows, legend rows, group labels, edge badges,
|
|
981
|
+
nodes, "+N more") snapped instantly; HTML chips (post-R490) now
|
|
982
|
+
ease through 200ms ease-out but SVG g still hard-cut. Same
|
|
983
|
+
baseline-transparent + transition-outline-color recipe brings
|
|
984
|
+
the SVG canvas into the unified keyboard motion vocabulary —
|
|
985
|
+
keyboard users tabbing between chip-row and SVG canvas see
|
|
986
|
+
ONE smooth fade timing instead of HTML-smooth-then-SVG-snap.
|
|
987
|
+
The cyan-300 (#67e8f9) target color matches R156's original
|
|
988
|
+
choice (legendAccent visual identity); only the transition
|
|
989
|
+
timing is new.
|
|
990
|
+
Note on cascade: SVG g elements rarely carry Tailwind
|
|
991
|
+
transition-* utility classes (Tailwind defaults are HTML-
|
|
992
|
+
centric), so the (0,1,0) specificity of .anet-topo-svg-focus
|
|
993
|
+
typically wins without !important. Adding !important defensively
|
|
994
|
+
anyway since the React component may add future inline styles
|
|
995
|
+
or Tailwind classes. Same trade-off as R490 (inline
|
|
996
|
+
style.transition still wins if added). */
|
|
997
|
+
.anet-topo-svg-focus {
|
|
998
|
+
outline: 2px solid transparent;
|
|
920
999
|
outline-offset: 2px;
|
|
1000
|
+
transition-property: outline-color !important;
|
|
1001
|
+
transition-duration: 200ms !important;
|
|
1002
|
+
transition-timing-function: ease-out !important;
|
|
1003
|
+
}
|
|
1004
|
+
.anet-topo-svg-focus:focus-visible {
|
|
1005
|
+
outline-color: #67e8f9;
|
|
921
1006
|
}
|
|
922
1007
|
|
|
923
1008
|
/* Round 46 — animated dashed spokes flowing from hub outward. Each spoke
|
package/package.json
CHANGED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* Round 494 verification: chip-row working + online chips gain
|
|
2
|
+
* `active:scale-95` press feedback, gated on the clickable branch
|
|
3
|
+
* (workingCount > 0 / onlineNodes.length > 0). Extends the chrome-
|
|
4
|
+
* strip press family (R492 Ring/Grid + R493 5 chrome buttons) into
|
|
5
|
+
* the chip-row scope.
|
|
6
|
+
*
|
|
7
|
+
* Verifies per chip:
|
|
8
|
+
* - DOM element resolvable (data-working-chip / data-online-chip)
|
|
9
|
+
* - className contains `active:scale-95` (since fixture has both chips
|
|
10
|
+
* with > 0 count → clickable branch active)
|
|
11
|
+
* - computed transition-property includes `transform`
|
|
12
|
+
* - source-file regex confirms class string wired
|
|
13
|
+
*/
|
|
14
|
+
import { chromium } from 'playwright';
|
|
15
|
+
import { readFileSync } from 'node:fs';
|
|
16
|
+
|
|
17
|
+
const TOKEN = JSON.parse(readFileSync('/home/vansin/.anet/config.json', 'utf8')).token;
|
|
18
|
+
const fresh = new Date(Date.now() - 60 * 1000).toISOString();
|
|
19
|
+
|
|
20
|
+
const browser = await chromium.launch({ headless: true });
|
|
21
|
+
const ctx = await browser.newContext({ viewport: { width: 1500, height: 1200 } });
|
|
22
|
+
await ctx.addCookies([{ name: 'anet_dashboard_session', value: `v3:${TOKEN}`, domain: '127.0.0.1', path: '/' }]);
|
|
23
|
+
await ctx.addInitScript(() => {
|
|
24
|
+
try {
|
|
25
|
+
localStorage.setItem('anet-theme', 'cyber');
|
|
26
|
+
localStorage.setItem('anet-topo-layout', 'ring');
|
|
27
|
+
sessionStorage.setItem('anet_v3_auth', '1');
|
|
28
|
+
} catch {}
|
|
29
|
+
});
|
|
30
|
+
await ctx.route('**/api/hub/status*', async (route) => {
|
|
31
|
+
const r = await route.fetch();
|
|
32
|
+
const b = await r.json();
|
|
33
|
+
const nid = (b.sessions || [])[0]?.network_id || 'default';
|
|
34
|
+
const mk = (alias, status) => ({
|
|
35
|
+
alias, status, model: 'claude-opus-4', runtime: 'claude-code-cli',
|
|
36
|
+
network_id: nid, project_dir: null,
|
|
37
|
+
created_at: fresh, updated_at: fresh, last_seen_at: fresh,
|
|
38
|
+
});
|
|
39
|
+
// Need both working and online > 0 so both chip variants enter clickable branch
|
|
40
|
+
await route.fulfill({ response: r, json: { ...b, sessions: [
|
|
41
|
+
mk('alpha·a1', 'working'),
|
|
42
|
+
mk('alpha·a2', 'idle'),
|
|
43
|
+
] } });
|
|
44
|
+
});
|
|
45
|
+
await ctx.route('**/api/hub/messages*', (r) => r.fulfill({ json: { messages: [] } }));
|
|
46
|
+
await ctx.route('**/api/hub/tasks*', (r) => r.fulfill({ json: { tasks: [] } }));
|
|
47
|
+
const page = await ctx.newPage();
|
|
48
|
+
await page.goto('http://127.0.0.1:3000/', { waitUntil: 'networkidle' });
|
|
49
|
+
await page.waitForSelector('[data-working-chip]', { timeout: 15000 });
|
|
50
|
+
await page.waitForTimeout(1000);
|
|
51
|
+
|
|
52
|
+
const probe = async (sel) => {
|
|
53
|
+
return await page.evaluate((s) => {
|
|
54
|
+
const el = document.querySelector(s);
|
|
55
|
+
if (!el) return null;
|
|
56
|
+
const cs = window.getComputedStyle(el);
|
|
57
|
+
return {
|
|
58
|
+
cls: el.className || '',
|
|
59
|
+
cls_has_scale95: /active:scale-95/.test(el.className || ''),
|
|
60
|
+
cls_has_translate: /hover:-translate-y-px/.test(el.className || ''),
|
|
61
|
+
tp: cs.transitionProperty,
|
|
62
|
+
td: cs.transitionDuration,
|
|
63
|
+
tp_has_transform: /transform/i.test(cs.transitionProperty || ''),
|
|
64
|
+
};
|
|
65
|
+
}, sel);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const wInfo = await probe('[data-working-chip]');
|
|
69
|
+
const oInfo = await probe('[data-online-chip]');
|
|
70
|
+
|
|
71
|
+
await browser.close();
|
|
72
|
+
|
|
73
|
+
const src = readFileSync('/home/vansin/agent-network-dashboard/app/components/TopoGraph.tsx', 'utf8');
|
|
74
|
+
const sWorking = /workingCount > 0\s*\?\s*'bg-green-500\/10 text-green-300 border-green-500\/20 hover:bg-green-500\/15 hover:border-green-500\/30 hover:-translate-y-px active:scale-95'/.test(src);
|
|
75
|
+
const sOnline = /onlineNodes\.length > 0\s*\?\s*'bg-cyan-500\/10 text-cyan-300 border-cyan-500\/20 hover:bg-cyan-500\/15 hover:border-cyan-500\/30 hover:-translate-y-px active:scale-95'/.test(src);
|
|
76
|
+
|
|
77
|
+
const results = {
|
|
78
|
+
working_dom_found: !!wInfo,
|
|
79
|
+
working_has_scale95: wInfo && wInfo.cls_has_scale95,
|
|
80
|
+
working_has_lift: wInfo && wInfo.cls_has_translate,
|
|
81
|
+
working_tp_transform: wInfo && wInfo.tp_has_transform,
|
|
82
|
+
online_dom_found: !!oInfo,
|
|
83
|
+
online_has_scale95: oInfo && oInfo.cls_has_scale95,
|
|
84
|
+
online_has_lift: oInfo && oInfo.cls_has_translate,
|
|
85
|
+
online_tp_transform: oInfo && oInfo.tp_has_transform,
|
|
86
|
+
source_working_wired: sWorking,
|
|
87
|
+
source_online_wired: sOnline,
|
|
88
|
+
};
|
|
89
|
+
const ok = Object.values(results).every(Boolean);
|
|
90
|
+
console.log(`${ok ? '✅' : '❌'} chip-row working+online active:scale-95 (R494):`, JSON.stringify(results),
|
|
91
|
+
'\n working tp:', wInfo && wInfo.tp,
|
|
92
|
+
'\n online tp:', oInfo && oInfo.tp);
|
|
93
|
+
process.exit(ok ? 0 : 1);
|