You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Captures the Interactive Explorer feedback from the 2026-05-08 tech call discussion of Hana's wireframe mockup (Figma node 213:394). Hana noted "corrections coming"; this issue tracks the Light-path subset that integrates with our shipped FTS work without re-opening the locked contracts.
Background
The mockup proposes a search UX that introduces a third semantic alongside our recent option C (locked in #164 / PR #166): two explicit buttons in the side panel — "Search Selected Areas" (viewport-scoped) and "Search Entire World" (full-corpus). EXPLORER_STATE.md §6 currently commits to option C with side-panel + result-pin overlay; the mockup overlays a viewport-scope toggle on top.
Heavy — revisit option A vs C entirely as design intent shifts (full A/B/C/two-button rethink).
Decision: Light first. Heavy deferred until we've shipped the substrate work in #169-#172 and have data on whether viewport-scoped search materially shifts user behavior.
Light-path spec — search-semantics
UI
Two buttons in the side panel below the search input + facet checkboxes (matching the Figma mockup):
"Search Selected Areas" (orange in mockup) — runs current query against samples whose lat/lng falls within the camera's current view rectangle.
The current single "Search" button → replaced by these two. Pressing Enter in the search input runs whichever was last clicked, defaulting to Search Entire World (preserves current behavior for keyboard users).
Backend
In doSearch(scope):
asyncfunctiondoSearch(scope){// ... existing instrumentation + token tokenization ...letviewportPredicate='';if(scope==='area'){constrect=viewer.camera.computeViewRectangle(viewer.scene.globe.ellipsoid);if(rect){constsouth=Cesium.Math.toDegrees(rect.south);constnorth=Cesium.Math.toDegrees(rect.north);constwest=Cesium.Math.toDegrees(rect.west);consteast=Cesium.Math.toDegrees(rect.east);// Dateline-crossing case (west > east): split into two ranges.// The lat/lng columns live in the lite parquet, joined as `l` in the CTE.if(west>east){viewportPredicate=` AND l.latitude BETWEEN ${south} AND ${north} AND (l.longitude BETWEEN ${west} AND 180 OR l.longitude BETWEEN -180 AND ${east}) `;}else{viewportPredicate=` AND l.latitude BETWEEN ${south} AND ${north} AND l.longitude BETWEEN ${west} AND ${east} `;}}}constresults=awaitdb.query(` WITH matches AS ( SELECT pid, label, source, place_name, (${score}) AS relevance_score FROM read_parquet('${facets_url}') WHERE ${searchWhere}${sourceFilterSQL('source')}${facetFilterSQL()} ORDER BY relevance_score DESC LIMIT 50 ) SELECT m.pid, m.label, m.source, l.latitude, l.longitude, m.place_name, m.relevance_score FROM matches m LEFT JOIN read_parquet('${lite_url}') l USING (pid) WHERE 1=1 ${viewportPredicate} ORDER BY m.relevance_score DESC, m.label `);}
The viewport predicate goes on the outer query (post-join), not the CTE — because the inner CTE searches sample_facets_v2 which doesn't have lat/lng. This means the CTE may return up to 50 matches that fail the viewport predicate; the outer LIMIT can drop us below 50 results in viewport-scoped mode. For v1 this is fine (users can pan to widen the area). A future tuning could increase the inner LIMIT to e.g. 200 when in area mode.
URL state
New query param ?search_scope=area|world. Hydrated by applyQueryToSearch(); written by writeQueryState().
Default: world (omitted from URL).
Camera position is the source of truth for what "area" means; no need to encode the rect in the URL — ?v=1&lat=…&lng=…&alt=… already captures it.
Result-pin overlay
The option C result-pin overlay (per EXPLORER_STATE.md §6) still applies for both scopes. Pin coordinates already reflect what was found; viewport-scope just narrows the candidate set.
Open question
Does Hana's design intent want "Search Selected Areas" as the primary button (left position) or the secondary? Mockup shows orange (selected areas) on the left and blue (entire world) on the right, suggesting selected-areas is primary. If so, the keyboard default may want to flip to area-scope. Defer until confirmed with Hana/Andrea.
Other mockup-derived items (separate from search semantics)
These are net-new UX work, no conflict with shipped contracts. Not in scope for the Light search-semantics PR; tracked here for future follow-ups:
Educational tooltips ("What is a Cluster?", "What is a Sample?") — onboarding boxes on the left edge of the explorer.
Tree-selection vocabularies for material / sample / sample-feature hierarchies — Hana to make a mockup diagram.
Top-level sample-type icons (5 per category) for missing-image fallback in sample cards.
Visual accessibility: halos around dots for color-blind / low-vision users.
Native Cesium control panel on the left edge — currently hidden; mockup shows it visible.
Quick Stats panel restructure — Selected Cluster moved into the same table as Quick Stats.
Visible "Copy Link to Selected View" button — currently we have a shareBtn; mockup styles it more prominently with a labeled button.
EXPLORER_STATE.md §6 amended: option C remains the default; the area-scoped variant is documented as a Light extension that does not require revisiting A/B/C
Out of scope
Heavy revisit of EXPLORER_STATE.md §6 (full A/B/C/two-button rethink).
Captures the Interactive Explorer feedback from the 2026-05-08 tech call discussion of Hana's wireframe mockup (Figma node 213:394). Hana noted "corrections coming"; this issue tracks the Light-path subset that integrates with our shipped FTS work without re-opening the locked contracts.
Background
The mockup proposes a search UX that introduces a third semantic alongside our recent option C (locked in #164 / PR #166): two explicit buttons in the side panel — "Search Selected Areas" (viewport-scoped) and "Search Entire World" (full-corpus). EXPLORER_STATE.md §6 currently commits to option C with side-panel + result-pin overlay; the mockup overlays a viewport-scope toggle on top.
Two implementation paths:
latitude/longitude BETWEENpredicate added. No contract change to Explorer FTS Track 2: search_index_v1 contract doc #169-Explorer FTS Track 5: GO/NO-GO decision gate #172.Decision: Light first. Heavy deferred until we've shipped the substrate work in #169-#172 and have data on whether viewport-scoped search materially shifts user behavior.
Light-path spec — search-semantics
UI
Two buttons in the side panel below the search input + facet checkboxes (matching the Figma mockup):
doSearch()behavior, post-PR explorer: interim recall fix — search description (#168 Direction A, knowingly slower) #177).The current single "Search" button → replaced by these two. Pressing Enter in the search input runs whichever was last clicked, defaulting to Search Entire World (preserves current behavior for keyboard users).
Backend
In
doSearch(scope):The viewport predicate goes on the outer query (post-join), not the CTE — because the inner CTE searches
sample_facets_v2which doesn't have lat/lng. This means the CTE may return up to 50 matches that fail the viewport predicate; the outer LIMIT can drop us below 50 results in viewport-scoped mode. For v1 this is fine (users can pan to widen the area). A future tuning could increase the inner LIMIT to e.g. 200 when in area mode.URL state
?search_scope=area|world. Hydrated byapplyQueryToSearch(); written bywriteQueryState().world(omitted from URL).?v=1&lat=…&lng=…&alt=…already captures it.Result-pin overlay
The option C result-pin overlay (per EXPLORER_STATE.md §6) still applies for both scopes. Pin coordinates already reflect what was found; viewport-scope just narrows the candidate set.
Open question
Does Hana's design intent want "Search Selected Areas" as the primary button (left position) or the secondary? Mockup shows orange (selected areas) on the left and blue (entire world) on the right, suggesting selected-areas is primary. If so, the keyboard default may want to flip to area-scope. Defer until confirmed with Hana/Andrea.
Other mockup-derived items (separate from search semantics)
These are net-new UX work, no conflict with shipped contracts. Not in scope for the Light search-semantics PR; tracked here for future follow-ups:
shareBtn; mockup styles it more prominently with a labeled button.Each of these gets its own issue once Hana's "corrections coming" iteration lands.
Acceptance for this issue (Light path only)
?search_scope=area|worldURL param, hydrated + writtendoSearch(scope)SQL conditionally adds the viewport predicate, with dateline-crossing handledOut of scope
Refs
#163 (UX rework umbrella), #165 (FTS umbrella), PR #166 (state contract option C), PR #177 (interim recall fix), Hana mockup Figma 213:394.