Skip to content

fix: droppable search navigates to results page; lock html+body scroll#44

Merged
mekarpeles merged 7 commits intomainfrom
fix/droppable-navigation
Apr 27, 2026
Merged

fix: droppable search navigates to results page; lock html+body scroll#44
mekarpeles merged 7 commits intomainfrom
fix/droppable-navigation

Conversation

@mekarpeles
Copy link
Copy Markdown
Member

@mekarpeles mekarpeles commented Apr 27, 2026

Summary

Two critical bugs exposed by the gap between what tests checked vs. what actually needed to work.

Bug 1 — Submit/Enter/See-all never navigated in droppable mode

`_submit()` always dispatched `ol-search` but never navigated. The existing test only checked `window.__olSearchFired === true` — not that the URL changed. Nobody caught it.

Fix:

  • Add `_buildSearchUrl(q, filters)` — constructs `new URL('/search', siteBase)` with all filter params via `URLSearchParams`
  • Make `ol-search` cancelable. Hosts that handle navigation themselves can call `e.preventDefault()` to suppress the fallback
  • `_submit()` and the "See all N results" button both do `window.location.href = _buildSearchUrl(...)` when `showFacets=true` and the event wasn't cancelled
  • Embedded mode (`showFacets=false`) is unchanged — no navigation added there

Bug 2 — Page behind overlay still scrollable

`document.body.style.overflow = 'hidden'` only locks ``. Many browsers (and the demo page) actually scroll ``. The overlay was `position:fixed` but the scrollbar remained visible behind it.

Fix: Lock both `document.documentElement` and `document.body` whenever the droppable search panel is open on any viewport (not only the mobile full-screen overlay). Restore both on close and in `disconnectedCallback`. The lock is keyed on `changed.has('_open') && this.showFacets` so embedded mode is unaffected.

TDD process

Playwright tests were written before the fixes (failing red), proving the regression, then the fixes made them green:

  • submit button → navigates to `/search?q=`
  • Enter key → navigates to `/search?q=`
  • "See all N results" → navigates to `/search?q=`
  • active filters appear in navigation URL
  • `preventDefault()` suppresses navigation
  • `body` + `documentElement` have `overflow:hidden` while mobile overlay is open
  • both restored to `''` on close
  • desktop droppable panel also locks scroll (new)

`AGENTS.md` updated with an explicit TDD section so this pattern is the default going forward.

Test plan

  • `npx vitest run` — 189 static-analysis tests pass
  • `npx playwright test tests/facet-and-submit.spec.js` — all navigation tests pass
  • `npx playwright test tests/mobile-overlay.spec.js` — scroll lock tests pass (mobile + desktop)
  • Manual: type query in droppable bar, press Enter → navigates to OL search page
  • Manual: click "See all N results" → navigates to OL search page
  • Manual: mobile overlay open → no page scrollbar visible behind overlay
  • Manual: desktop panel open → page behind panel is not scrollable

Copilot AI review requested due to automatic review settings April 27, 2026 16:49
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes droppable (showFacets=true) search submit behavior to navigate to a results URL and improves mobile overlay scroll-lock by locking both <body> and <html>, with accompanying Playwright/Vitest coverage and process documentation updates.

Changes:

  • Add fallback navigation for droppable submit + “See all results” via _buildSearchUrl() and a cancelable ol-search event.
  • Lock/unlock both document.body and document.documentElement scrolling when the mobile overlay is open/closed (including cleanup on disconnect).
  • Expand Playwright coverage for navigation + scroll lock; update testing/process docs (TDD guidance).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/components/ol-search-bar.js Adds _buildSearchUrl(), cancelable ol-search, fallback navigation, and html+body scroll lock.
frontend/tests/facet-and-submit.spec.js Adds Playwright navigation tests for submit/Enter/See-all and cancelable-event suppression.
frontend/tests/mobile-overlay.spec.js Adds Playwright assertions for html+body overflow locking/restoration during overlay.
frontend/src/components/ol-search-bar.panel-overlay.test.js Adjusts static-analysis slice length to keep overlay-focus contract test stable.
AGENTS.md Documents a TDD workflow expectation for interactive bug fixes and navigation assertions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frontend/src/components/ol-search-bar.js Outdated
Comment thread frontend/src/components/ol-search-bar.js Outdated
Comment thread frontend/src/components/ol-search-bar.js Outdated
Comment thread frontend/tests/facet-and-submit.spec.js
mekarpeles added a commit that referenced this pull request Apr 27, 2026
- Use _scrollLockActive flag in disconnectedCallback instead of
  _mobileExpanded to correctly release scroll lock when component
  is removed while overlay is open
- Save/restore _prevBodyOverflow and _prevDocumentOverflow before
  locking so we never clobber pre-existing inline overflow styles
- Use new URL('/search', siteBase) to safely handle trailing slash
  in siteBase (fixes potential double-slash in navigation URL)
- Add Playwright test asserting active filters appear in navigation URL
- Widen updated() slice to 2000 chars in panel-overlay static test
Issue #44 — two critical bugs found because tests only checked that
ol-search fired, not that navigation happened:

Navigation (droppable mode):
- Add _buildSearchUrl(q, filters) that constructs siteBase/search?q=...
  with full filter params serialized as OL search URL query params
- Make ol-search event cancelable — hosts that handle navigation
  themselves call e.preventDefault() to suppress the fallback
- _submit() and "See all N results" both navigate via window.location.href
  when showFacets=true and event not prevented
- Embedded mode (showFacets=false) is unaffected

Body scroll lock:
- Lock document.documentElement.style.overflow in addition to document.body;
  many browsers/frameworks scroll <html>, leaving a page scrollbar behind
  the position:fixed overlay
- Restore both on close and in disconnectedCallback

TDD: Playwright tests written BEFORE the fix (red → green):
- submit button / Enter key / "See all N" each navigate to /search?q=
- preventDefault() suppresses navigation
- document.body + documentElement overflow:hidden while overlay open
- both restored to '' when overlay closes

AGENTS.md: explicit TDD section requiring a failing test before any fix
- Use _scrollLockActive flag in disconnectedCallback instead of
  _mobileExpanded to correctly release scroll lock when component
  is removed while overlay is open
- Save/restore _prevBodyOverflow and _prevDocumentOverflow before
  locking so we never clobber pre-existing inline overflow styles
- Use new URL('/search', siteBase) to safely handle trailing slash
  in siteBase (fixes potential double-slash in navigation URL)
- Add Playwright test asserting active filters appear in navigation URL
- Widen updated() slice to 2000 chars in panel-overlay static test
Vitest: assert scroll lock is gated on _open + showFacets, not
only _mobileExpanded, so desktop droppable panel also locks scroll.

Playwright: two desktop tests — overflow:hidden while panel open,
overflow restored after Escape closes it.

Tests fail red against current code; will go green once the lock
trigger is moved from changed.has('_mobileExpanded') to changed.has('_open').
…e overlay

Move scroll-lock trigger from changed.has('_mobileExpanded') to
changed.has('_open'), with condition this._open && this.showFacets.
This ensures the page behind the search panel cannot scroll on
desktop viewports just as it cannot on mobile.
@mekarpeles mekarpeles force-pushed the fix/droppable-navigation branch from 6eb686e to 4acf1fd Compare April 27, 2026 17:37
@mekarpeles mekarpeles merged commit 06171ae into main Apr 27, 2026
2 checks passed
@mekarpeles mekarpeles deleted the fix/droppable-navigation branch April 27, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants