feat(map): simplify search UX/UI#1061
Conversation
Parameterize peek height, dismissability, and analytics event names so a second bottom sheet (mobile search) can reuse the drawer snap mechanics. Defaults preserve the merchant drawer behavior exactly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mode tabs
The Worldwide/Nearby scope toggle now lives inside the list panel only.
At rest the input carries a teal '{n} nearby' pill; it yields the slot to
the clear button as soon as the user types.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
While a nearby filter is active the Nearby tab shows the filtered count, including (0). A zero-match filter renders an empty state with a 'Search worldwide' CTA instead of a blank list. Panel placeholder becomes the neutral 'Search places...' (single-input metaphor; scope lives in the toggle), retiring the per-mode placeholder keys. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The merchant list panel becomes an always-present bottom sheet on mobile: peek (grabber + single input + count pill) <-> full panel, driven by a second drawer-gesture-controller instance (canDismiss false, search_sheet_* analytics). Tapping the peek facade opens the list without popping the keyboard; the floating search bar is now desktop-only. Bottom map controls (scale, OSM attribution) are lifted above the peek sheet on mobile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fter review
Review findings from the multi-agent pass:
- determineSnapState now honors the controller's peek height, so the
search sheet snaps back to 110px instead of the drawer's 140px
(+ regression test)
- reset the sheet gesture when the merchant drawer takes the bottom
edge, so an unmount mid-drag can't strand the captured pointer
- the whole peek facade is a swipe surface, not just the grabber strip;
facade exposes aria-expanded and its visible label (incl. count)
- floating bar and sheet now derive from one init-locked layout
decision, so resizes can't yield zero or two search surfaces
- touchcancel handling on the list collapse-drag; grabber aria-controls
- trailing slot is click-transparent so the count pill no longer blocks
taps on the input
- panel input emits search_input_focus {source: panel}
- attribution lift reads SEARCH_SHEET_PEEK_HEIGHT via a CSS custom
property; sheet bottom padding uses the max() safe-area floor
- rewrite stale merchant-list-panel e2e specs for the single-input UX
(9 passing) and add a zero-match CTA spec
- translation polish: terminology consistency for the new keys in
fr/it/nl/ru/bg/pt-BR/es/de
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The expanded sheet header (search input row, scope toggle, category chips) now acts as a drag surface like the grabber, mirroring the merchant drawer's draggable header. An 8px vertical slop separates taps from drags so the input, toggle and chips stay tappable; once dragging, the pointer is captured so releasing over a chip doesn't click it. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Render height as calc(spring + env(safe-area-inset-bottom)) capped at 100dvh, so the home-indicator inset is added only on devices that have one instead of being budgeted into the constant. Attribution lift mirrors the same calc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
✅ Deploy Preview for btcmap ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR refactors the map search interface to use a mobile-optimized peek/expanded sheet model with configurable gesture controls, while simplifying the desktop search experience into a unified neutral-placeholder input that displays nearby merchant counts. Gesture infrastructure is made reusable through configurable peek heights and event names. UI constants and helpers are updated to support count badge formatting and 250-item display caps. Desktop layout conditionally hides the search bar when the panel is open. All locales receive unified search placeholder and nearby count label updates. ChangesMobile Search Sheet with Peek/Expand Gestures and Unified Interface
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/routes/map/components/MerchantListPanel.svelte (1)
10-15: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winSeparate type imports from value imports.
The import statement mixes type and value imports using inline
typekeywords. According to the coding guidelines, type imports should be in separateimport typestatements.♻️ Refactor to separate imports
+import type { CategoryCounts, CategoryKey } from "$lib/categoryMapping"; import { CATEGORY_ENTRIES, - type CategoryCounts, - type CategoryKey, placeMatchesCategory, } from "$lib/categoryMapping";As per coding guidelines: "Separate type imports from value imports using
import type { ... }for types only andimport { ... }for values only".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/routes/map/components/MerchantListPanel.svelte` around lines 10 - 15, The current import mixes runtime values and TypeScript types; split them into two imports: keep runtime symbols (CATEGORY_ENTRIES, placeMatchesCategory) in the regular import and move types (CategoryCounts, CategoryKey) into a separate "import type" statement. Update the import that currently references CATEGORY_ENTRIES, CategoryCounts, CategoryKey, placeMatchesCategory so you have one line importing CATEGORY_ENTRIES and placeMatchesCategory, and another "import type" line importing CategoryCounts and CategoryKey.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/routes/map/components/MerchantListPanel.svelte`:
- Around line 892-916: The peek facade button currently (bound to facadeElement
and handled by handlePeekTap) only has aria-expanded; add aria-label and
aria-controls for screen readers by giving the button a descriptive aria-label
matching the grabber's label and set aria-controls to the id of the peek
panel/sheet element it toggles (use the same panel id used elsewhere for the
grabber). Ensure the aria-controls value exactly matches the target panel's id
and keep aria-expanded in sync when state changes in handlePeekTap/sheetGesture
logic.
---
Outside diff comments:
In `@src/routes/map/components/MerchantListPanel.svelte`:
- Around line 10-15: The current import mixes runtime values and TypeScript
types; split them into two imports: keep runtime symbols (CATEGORY_ENTRIES,
placeMatchesCategory) in the regular import and move types (CategoryCounts,
CategoryKey) into a separate "import type" statement. Update the import that
currently references CATEGORY_ENTRIES, CategoryCounts, CategoryKey,
placeMatchesCategory so you have one line importing CATEGORY_ENTRIES and
placeMatchesCategory, and another "import type" line importing CategoryCounts
and CategoryKey.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 5c835d3a-1a75-45f1-9f30-d26bcfe811ac
📒 Files selected for processing (22)
src/components/SearchInput.sveltesrc/lib/analytics.tssrc/lib/drawerConfig.tssrc/lib/drawerGestureController.tssrc/lib/drawerGestureUtils.test.tssrc/lib/drawerGestureUtils.tssrc/lib/i18n/locales/bg.jsonsrc/lib/i18n/locales/de.jsonsrc/lib/i18n/locales/en.jsonsrc/lib/i18n/locales/es.jsonsrc/lib/i18n/locales/fr.jsonsrc/lib/i18n/locales/it.jsonsrc/lib/i18n/locales/nl.jsonsrc/lib/i18n/locales/pt-BR.jsonsrc/lib/i18n/locales/ru.jsonsrc/lib/utils.test.tssrc/lib/utils.tssrc/routes/map/+page.sveltesrc/routes/map/components/MapSearchBar.sveltesrc/routes/map/components/MerchantListPanel.sveltesrc/routes/map/components/NearbyCountPill.sveltetests/merchant-list-panel.spec.ts
- Nearby name filter now searches the full fetched set (allMerchants, up to the fetch ceiling), not just the 99 displayed rows, so a match ranked past the display cap no longer shows a false 'nothing nearby' CTA. Display stays capped at 99 (#3) - single nearbyFilter reset via reactive on !isOpen, dropping the four scattered clears that diverged (stale filter after item tap) (#1) - collapsing the sheet cancels any pending/in-flight worldwide search so a late response can't reopen it (#2) - remove unreachable isSearching spinner branch + dead prop in the desktop floating bar (#9) - formatNearbyCount now delegates to formatNearbyPillCount (#7a) - dismiss event is optional config, omitted when canDismiss:false (#7b) - grabber is not a redundant tab stop / SR control at peek (#8) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the bottom-latched peek with a floating rounded input card (side + bottom margins, raised off the bottom edge). Dragging up continuously docks it into the full-width sheet (margins + corner radius interpolate to 0 as it expands). Restore the drag handle on top, slim the peek to 72px, and style the input as a clear filled field so it reads as searchable. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Empty input browses the nearby list; typing (>=3 chars) searches worldwide by name, shorter falls back to nearby. Removes the mode toggle, the 'nothing nearby matches' CTA, and the client-side nearby name-filter (with its allMerchants backing list) — typing now searches everywhere, so a nearby match is always findable and the toggle's friction is gone. Raise the nearby display/badge cap from 99 to 250. Style the expanded panel input as a filled field for visibility. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drops the now-unused search.worldwide/nearby, switchToWorldwide, filterResults, noNearbyMatches(+Hint), searchWorldwide and aria.switchMode keys from all 9 locales, plus the nearby_mode_click / worldwide_mode_click / search_worldwide_cta_click events that the removed mode toggle and CTA used to fire. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the OSM/supporter attribution to a compact (i) button by default (matching the merchant detail / area maps), drop the rule that lifted the scale bar and attribution above the search card, and raise the floating search peek (56px bottom inset) so it sits above the scale bar, the compact attribution and the tile-loading indicator — the same stacking order as the search bar on main. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- The initial camera is set programmatically (no moveend), so the nearby list/count stayed empty until the user panned or opened the panel — the peek pill showed no count. Trigger updateMerchantList once when the map and places are first ready. - The compact AttributionControl renders expanded on load (maplibregl-compact-show); collapse it to the (i) button so the bottom edge stays clear. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Very nice 😍 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/lib/constants.ts`:
- Around line 69-73: Search the src/lib/constants.ts file for comments that
reference the old value of 99 related to merchant limits or nearby browse
functionality, particularly in the nearby-flow context. Update all instances of
these stale cap references from 99 to 250 to align with the updated
MERCHANT_LIST_MAX_ITEMS constant, ensuring consistency across all documentation
and comments in the file.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 50bd70e3-94dc-4fcb-be63-18680991362c
📒 Files selected for processing (20)
src/components/SearchInput.sveltesrc/lib/analytics.tssrc/lib/constants.tssrc/lib/drawerConfig.tssrc/lib/drawerGestureController.tssrc/lib/i18n/locales/bg.jsonsrc/lib/i18n/locales/de.jsonsrc/lib/i18n/locales/en.jsonsrc/lib/i18n/locales/es.jsonsrc/lib/i18n/locales/fr.jsonsrc/lib/i18n/locales/it.jsonsrc/lib/i18n/locales/nl.jsonsrc/lib/i18n/locales/pt-BR.jsonsrc/lib/i18n/locales/ru.jsonsrc/lib/merchantListStore.test.tssrc/lib/utils.test.tssrc/lib/utils.tssrc/routes/map/+page.sveltesrc/routes/map/components/MapSearchBar.sveltesrc/routes/map/components/MerchantListPanel.svelte
💤 Files with no reviewable changes (11)
- src/lib/i18n/locales/en.json
- src/lib/i18n/locales/fr.json
- src/lib/i18n/locales/it.json
- src/lib/i18n/locales/es.json
- src/lib/analytics.ts
- src/lib/i18n/locales/de.json
- src/lib/i18n/locales/pt-BR.json
- src/routes/map/components/MapSearchBar.svelte
- src/lib/i18n/locales/ru.json
- src/lib/i18n/locales/bg.json
- src/lib/i18n/locales/nl.json
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/SearchInput.svelte
- src/lib/drawerGestureController.ts
- src/lib/utils.test.ts
Rewrite the toggle/CTA-based specs for the new behavior: empty input browses nearby, typing searches worldwide (asserted via the search-only 'Show all on map' control), clearing returns to nearby. Disambiguate the floating-bar-vs-panel input (now sharing an accessible name) by count and scope instead of visibility. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Once the panel opens on desktop the floating bar (and its count pill) unmounts, and the removed Nearby tab used to carry the count. Add a muted 'N nearby' line under the search field — nearby mode only, hidden while searching. Mobile keeps using the peek/input pills. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/merchant-list-panel.spec.ts`:
- Around line 284-288: The test has a race condition where panelInput.fill() on
line 284 can trigger the `/api/search/places` request before the waitForResponse
listener is registered on line 285, causing intermittent timeouts. Reorder the
operations by registering the response waiter first (before the fill action),
then trigger the input fill while the listener is actively waiting. This ensures
the network request is captured reliably instead of being missed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4dbf050d-f8ff-4e2b-957a-6885f563bb68
📒 Files selected for processing (1)
tests/merchant-list-panel.spec.ts
Desktop has room for the full credit; keep the compact (i) collapse just for mobile where the floating search needs the bottom edge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review feedback: - delete the now-unused formatNearbyCount (the segmented tab that used it is gone; the pill uses formatNearbyPillCount) - a transient search failure no longer wipes the user's typed query — keep the query + search mode and just toast, instead of exitSearchMode() - guard against a late search response reopening a closed panel/sheet: bail after the awaits if the list is no longer open Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract the drawer collapse caret into a reusable CollapseButton with a round light background so it reads clearly as a button, and use it in both the merchant drawer and the search sheet. The search sheet's caret is now the keyboard/AT collapse control (grabber demoted to a decorative drag affordance), and collapsing moves focus to the peek facade so AT users aren't stranded on a hidden control. Gate the sheet gesture subscription to mobile and drop the dead aria.expandMerchantList key. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- constants: update stale 'nearest 99' comments to 250 (cap was raised) - e2e: arm the search-response waiter before typing so a fast response can't land before the wait registers (flaky-test fix) - peek facade: add aria-controls to the expand button (matches the collapse caret); intentionally no aria-label — the visible 'Search places… N nearby' text is the better accessible name Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/routes/map/components/MerchantDrawerMobile.svelte (1)
263-269: 💤 Low valueConsider adding
aria-controlsfor consistency with MerchantListPanel.The CollapseButton in MerchantListPanel (lines 520-526) includes
aria-controls="merchant-sheet-content"andaria-expanded="true". For consistency and explicit association with the controlled content, consider adding these here:<CollapseButton onClick={() => { trackEvent('drawer_collapse_button_click'); drawerGesture.collapse(); }} ariaLabel={$_('mapDrawer.collapseDrawer')} + aria-controls="drawer-content" + aria-expanded="true" />The drawer handle already provides ARIA state, so this is optional.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/routes/map/components/MerchantDrawerMobile.svelte` around lines 263 - 269, Add aria-controls and aria-expanded attributes to the CollapseButton component in MerchantDrawerMobile.svelte for consistency with the identical CollapseButton in MerchantListPanel. Set aria-controls to reference the drawer content element (use the same identifier as MerchantListPanel) and set aria-expanded to the appropriate boolean state that reflects whether the drawer is expanded or collapsed. This improves accessibility by explicitly associating the button with the content it controls, matching the pattern already established in MerchantListPanel.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/routes/map/components/MerchantDrawerMobile.svelte`:
- Around line 263-269: Add aria-controls and aria-expanded attributes to the
CollapseButton component in MerchantDrawerMobile.svelte for consistency with the
identical CollapseButton in MerchantListPanel. Set aria-controls to reference
the drawer content element (use the same identifier as MerchantListPanel) and
set aria-expanded to the appropriate boolean state that reflects whether the
drawer is expanded or collapsed. This improves accessibility by explicitly
associating the button with the content it controls, matching the pattern
already established in MerchantListPanel.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: be25790f-71b6-41a8-8237-47b5a4be0c22
📒 Files selected for processing (15)
src/components/CollapseButton.sveltesrc/lib/i18n/locales/bg.jsonsrc/lib/i18n/locales/de.jsonsrc/lib/i18n/locales/en.jsonsrc/lib/i18n/locales/es.jsonsrc/lib/i18n/locales/fr.jsonsrc/lib/i18n/locales/it.jsonsrc/lib/i18n/locales/nl.jsonsrc/lib/i18n/locales/pt-BR.jsonsrc/lib/i18n/locales/ru.jsonsrc/lib/utils.tssrc/routes/map/+page.sveltesrc/routes/map/components/MerchantDrawerMobile.sveltesrc/routes/map/components/MerchantListPanel.sveltetests/merchant-list-panel.spec.ts
💤 Files with no reviewable changes (9)
- src/lib/i18n/locales/es.json
- src/lib/i18n/locales/ru.json
- src/lib/i18n/locales/en.json
- src/lib/i18n/locales/nl.json
- src/lib/i18n/locales/it.json
- src/lib/i18n/locales/de.json
- src/lib/i18n/locales/fr.json
- src/lib/i18n/locales/pt-BR.json
- src/lib/i18n/locales/bg.json
🚧 Files skipped from review as they are similar to previous changes (1)
- tests/merchant-list-panel.spec.ts
There was a problem hiding this comment.
Pull request overview
This PR simplifies the map search UX by replacing the Worldwide/Nearby scope toggle with a single search input, and introducing a mobile bottom-sheet “peek → expand” interaction that mirrors the merchant drawer.
Changes:
- Replace scope-toggle search with a single-input model (empty/short query shows nearby; ≥3 chars triggers worldwide search).
- Introduce a draggable mobile search sheet + nearby count pill, and unify drawer/search collapse controls via a shared
CollapseButton. - Update analytics events, nearby list cap (99 → 250), translations, and E2E/unit tests to match the new behavior.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/merchant-list-panel.spec.ts | Updates E2E assertions for the single-input + mobile peek sheet behavior. |
| src/routes/map/components/NearbyCountPill.svelte | Adds reusable “nearby count” pill component for floating/peek UI. |
| src/routes/map/components/MerchantListPanel.svelte | Reworks panel into a mobile bottom sheet with gestures; removes mode toggle; integrates count pill. |
| src/routes/map/components/MerchantDrawerMobile.svelte | Replaces custom collapse button markup with shared CollapseButton. |
| src/routes/map/components/MapSearchBar.svelte | Simplifies floating bar to single input + optional nearby count pill (desktop-only). |
| src/routes/map/+page.svelte | Updates search flow (≥3 chars worldwide), abort behavior, initial nearby population, attribution compacting, and desktop-only floating bar. |
| src/lib/utils.ts | Replaces nearby count formatter with pill-oriented formatNearbyPillCount. |
| src/lib/utils.test.ts | Adds unit tests for formatNearbyPillCount. |
| src/lib/merchantListStore.test.ts | Updates expectations for new nearby list cap (250). |
| src/lib/i18n/locales/bg.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/de.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/en.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/es.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/fr.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/it.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/nl.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/pt-BR.json | Updates search strings for single-input + nearby count label. |
| src/lib/i18n/locales/ru.json | Updates search strings for single-input + nearby count label. |
| src/lib/drawerGestureUtils.ts | Extends snap logic to support a custom peek height. |
| src/lib/drawerGestureUtils.test.ts | Adds coverage for custom peek-height snap behavior. |
| src/lib/drawerGestureController.ts | Adds options for peek height, dismiss disabling, and per-surface analytics events. |
| src/lib/drawerConfig.ts | Adds SEARCH_SHEET_PEEK_HEIGHT. |
| src/lib/constants.ts | Raises nearby list cap to 250 and updates docs/comments accordingly. |
| src/lib/analytics.ts | Exports EventName and adds new search-sheet events; removes toggle events. |
| src/components/SearchInput.svelte | Adds filled variant and pointer-events handling for trailing slot. |
| src/components/CollapseButton.svelte | Adds shared collapse caret button for drawers/sheets. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- e2e: assert the removed scope radios are absent via toHaveCount(0) (both Worldwide + Nearby) instead of not.toBeVisible(), which also passes for a merely-hidden element - MapSearchBar: correct the stale comment — there's no scope toggle in the panel anymore (empty box browses nearby, typing searches worldwide) - peek facade: drop the self-referential aria-controls (it pointed at its own wrapper); aria-expanded already conveys the disclosure Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The search sheet floats now — the safe-area clearance comes from the card's bottom inset, not from adding env() to the height. Clarify both peek-height constants. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirror the body-branch !isLoadingList guard on the status-row branch so the spinner takes precedence in both regions (same fix as #1067 on main, applied here since this branch reworked the panel). Avoids a contradictory 'zoom in' link flashing next to the loading spinner. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Single search input for the map
Replaces the map's Worldwide/Nearby toggle with one search box, so people no longer have
to choose a scope before searching. On mobile it becomes a floating, draggable search
card. From the "Search UX — single input" design.
How search works now
with a count.
rank first. Clearing the box returns you to the nearby list.
already covers everywhere, so there's nothing to switch.
Mobile
it to open without the keyboard popping up — so you can browse nearby first.
the merchant detail drawer.
never covers the tile-loading indicator.
Desktop
Map info
opening the panel).
remain on desktop.
Worth confirming (intended, not bugs)
characters.
(re-opening starts fresh on nearby).
Analytics
nearby_mode_click, search_worldwide_cta_click. New mobile-sheet events worth tracking:
search_sheet_tap_expand, search_sheet_swipe_expand, search_sheet_swipe_collapse.
Summary by CodeRabbit
Release Notes
New Features
Improvements
Updates
Bug Fixes
Documentation