mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-09-25 15:03:46 +00:00
## Summary The observer-comparison page (`#/compare`) is a powerful side-by-side overlap tool but was reachable from exactly one place — an icon-only 🔍 button in the observers page header. Most operators never found it. This PR promotes it to an IA citizen with **three new entry points** plus breadcrumbs back from the compare page to each observer's detail page. Red commit: `f937d29658e25973786f88a9ddeaaa33768f269e` (test asserts all three new affordances are present + navigate correctly; would have caught the original undiscoverability). Green commit: `5ceb34b66d780a971d3a43de06a0744445bdbecf`. ## Design rationale Three orthogonal user paths reach the same goal: - **Operator who lands on `/observers`** sees a labeled button — no more icon-guessing — and a row-selection workflow for direct manipulation ("pick two, compare"). - **Operator who lands on a specific observer's page** sees an in-context "Compare with…" picker — the comparison is parameterised with the current observer, removing the cognitive jump back to the list. - **Operator who already has two observer IDs** can still hit `#/compare?a=…&b=…` directly — legacy deep-links regression-guarded by the E2E. Plus: every compare-page view now shows `Observers › <A> ⇆ <B>` breadcrumbs that link back to each observer's detail page, so users can navigate sideways instead of bouncing through the list. ## Entry points added | # | Surface | Affordance | File:line | |---|---|---|---| | A | `/observers` header | `<button>` labeled "🔍 Compare observers" | `public/observers.js:125-130` | | B | `/observers/<id>` header | "Compare with…" `<select>` + Compare button | `public/observer-detail.js:90-103`, `:128-145`, `:436-456` | | D | `/observers` table | Per-row checkbox column + "Compare selected (N)" button enabled at exactly 2 | `public/observers.js:131-137`, `:295-302`, `:148-167`, `:354-378` | | breadcrumbs | `/compare` page | `data-role="compare-breadcrumbs"` with linked anchors → both detail pages | `public/compare.js:108`, `:202-228` | The pre-existing 🔍 link was REMOVED and replaced by (A) — the issue explicitly called for the icon-only affordance to go away. ## Before — current state on staging - Observers page header has only a bare 🔍 icon — no text label, indistinguishable from a generic search affordance. - Observer-detail page has zero comparison affordances; the user has to back out, find the observers list, locate the icon, then re-select both observers from scratch. - Compare page has a single back-arrow to `/observers` but no breadcrumb links to either compared observer's detail page. ## After — each new entry point browser-verified locally Built `cmd/server`, ran against `test-fixtures/e2e-fixture.db` on `:13581`, drove via headless chromium. Each step taken from a clean reload, screenshot captured (attached separately to the requesting session): - (A) Observers page header now shows a clearly-labeled "🔍 Compare observers" button alongside a "⚖️ Compare selected (N)" button (disabled when count !== 2). - (D) Two rows checked → "Compare selected (2)" enables → click → navigates to `#/compare?a=…&b=…` with both selects pre-populated and breadcrumbs reading `Observers › Kennedy Repeater ⇆ GY889 Repeater`. - (B) Observer-detail header now hosts a "Compare with…" `<select>` populated with the 30 other observers + a Compare button (disabled until a target is picked) → pick + click → navigates with the current observer pre-set as A. - Legacy `#/compare?a=…&b=…` deep-link still pre-populates both selects unchanged (covered by the E2E regression guard). ## Test plan - New: `test-issue-1640-compare-discovery-e2e.js` — 9 assertions across all three entry points + breadcrumbs + legacy-deep-link regression guard. Wired into `.github/workflows/deploy.yml`. - Local browser-verified each new affordance end-to-end (screenshots above). - `node --check test-issue-1640-compare-discovery-e2e.js` ✅ - Preflight clean (all 11 gates ✅), see below. ## Preflight checklist ``` ── [GATE] PII ── ✅ pass ── [GATE] Branch scope ── ✅ pass (5 files: 1 workflow, 3 frontend, 1 E2E) ── [GATE] Red commit ── ✅ pass (f937d29 verified failing) ── [GATE] CSS-var defined ── ✅ pass ── [GATE] CSS self-fallback ── ✅ pass ── [GATE] LIKE-on-JSON ── ✅ pass ── [GATE] Sync migration ── ✅ pass ── [GATE] Async-migration gate ── ✅ pass ── [GATE] XSS sinks ── ✅ pass ── [WARN] img/SVG ratio ── ✅ pass ── [WARN] Themed <img> SVG ── ✅ pass ── [WARN] Fixture coverage ── ✅ pass ═══ Preflight clean. ═══ ``` ## Accessibility - (A) and "Compare selected" buttons carry both visible text AND `aria-label`; disabled state uses both `disabled` and `aria-disabled="true"`. - (B) picker has an `<label class="sr-only">` plus `aria-label` for screen readers. - (D) per-row checkbox has `aria-label="Select <observer name> for comparison"`. - Breadcrumbs use `<nav aria-label="Compare breadcrumbs">` with a meaningful `›` separator (aria-hidden). ## Out of scope - The compare engine itself (`public/compare.js` data flow) is untouched. - New comparison metrics (track #671). - Analytics-nav link suggested as option (C) in the issue — covered by (A) which is more visible at the same top-nav tier; happy to add later if needed. Fixes #1640 --------- Co-authored-by: clawbot <bot@openclaw>