Skip to content

feat(render_map_tool): results carousel instead of the side list - #292

Open
mattpodwysocki wants to merge 7 commits into
mainfrom
feat/render-map-carousel
Open

mattpodwysocki wants to merge 7 commits into
mainfrom
feat/render-map-carousel

Conversation

@mattpodwysocki

@mattpodwysocki mattpodwysocki commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Description

Moves render_map_tool's numbered side list to a results carousel along the bottom of the map, the pattern ChatGPT uses for its built-in place results. Closes #283.

  • Place pins: white pins with a Maki icon for the place's category (Search Box's maki name, else matched from the category, else a plain marker), turning black when selected, like ChatGPT's place results and OpenAI's layout guidance. About 20 common icons are inlined (~12 KB, CC0). Numbered badges stay where the number means something: a caller's numbered label (visit order), optimized stops, start/end.
  • Cards: name, category, distance and popularity, plus the photo once it loads. A second line shows today's hours and the phone number from Place Details.
  • Selected pin: the selected place's pin turns black (a numbered badge turns white), comes to the front and shows the place name under it. The matching card gets a border. The first card starts selected.
  • Sync both ways: swiping selects the card nearest the middle, clicking a card selects it, and clicking a pin scrolls to its card. The map only pans when the selected pin is off screen or hidden behind the cards.
  • No popups for carousel pins. Pins without a card (route ends, the search center) keep theirs.
  • Layout: the carousel sits above the Mapbox logo and attribution, the legend moves up above it, and fit-to-bounds padding accounts for both.
  • Today's hours: parsed from OSM opening_hours for simple rules (Mo-Fr 07:00-19:00; Sa,Su 08:00-17:00, Su off, 24/7, wrap-around day ranges). Anything else shows no hours rather than wrong ones. No "Open now", since the viewer's clock may be in a different time zone than the place.
  • OpenAI's UI guidelines (fourth commit): every card has a picture (the place's icon as a placeholder when there's no photo), labeled for screen readers; numbered badges pick dark or white text by contrast; and the tool description asks the model not to list the places again after rendering. Still open from those guidelines: one action per card (render_map_tool: click a place to ask the model about it #284), and an Expand-to-fullscreen button (render_map_tool: fullscreen button #286).
  • Light and dark: cards, summary chip, legend and messages follow the host's theme (hostContext.theme at ui/initialize and on host-context-changed), falling back to prefers-color-scheme, and use the host's style variables (--color-background-primary, --color-text-primary, …) when sent. The map and pins look the same in both.
  • Tool and schema descriptions say "carousel" instead of "panel".

Notes

Testing

  • npm test: 1117 pass. New tests cover card/pin selection, pin click scrolling to its card, swipe selection, pan-only-when-hidden, fit padding with the carousel, legend position, and 11 hours-parsing cases.
  • npm run lint, tsc, npm run build clean.
  • Rendered in headless Chrome at 800x560 and 400x600, in light and dark, from a live category_search_tool result (coffee near SF City Hall): cards, photos, hours and phone all fill in, and card click, pin click and selection sync work. That pass found a pin just above the cards whose name label was hidden behind them, fixed in the second commit (pan when the label is hidden, and only as far as needed). It also showed the summary chip covering the zoom-in button (already the case on main); the third commit moves the zoom buttons below it, copying feat(render_map_tool): live traffic and Satellite/Traffic buttons on the map #278's placeTopLeftControls as-is so the two PRs merge cleanly.
  • Not yet checked inside Claude Desktop or ChatGPT.
pr292-carousel-phone-dark pr292-carousel-wide-dark

Checklist

  • I've added/updated tests as needed
  • I've updated documentation if necessary (CHANGELOG, tool descriptions)
  • Checked in Claude Desktop and ChatGPT

🤖 Generated with Claude Code

Place results now show as swipeable cards along the bottom of the map,
like ChatGPT's place results. The selected card and its pin stay in
sync: swiping or clicking a card highlights its pin (white, on top,
with the name under it) and pans only when the pin is hidden; clicking
a pin scrolls to its card. Pins with a card no longer open popups.
Cards show today's hours parsed from simple OSM opening_hours.

Closes #283

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@mattpodwysocki
mattpodwysocki requested a review from a team as a code owner October 19, 2026 20:31
mattpodwysocki and others added 6 commits October 19, 2026 16:31
Found in a headless render: a pin just above the carousel kept its name
label hidden behind the cards. Pan when the label (not just the pin)
would be hidden, do it for pin clicks too, and pan only as far as
needed instead of recentering, so nearby pins stay in view.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The "6 results for ..." chip sat on top of the zoom-in button. Same
placeTopLeftControls fix as #278, copied as-is so the two merge cleanly.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Every card has a picture: Assembly's marker icon on a muted tile until
  a photo loads, or when there is none, labeled for screen readers.
- Pin numbers pick dark or white text by WCAG contrast; white on the
  default orange was 2.8:1.
- The tool description asks the model not to repeat the places the
  cards already show.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…ange numbers

Matches ChatGPT's place results and OpenAI's UI guidance: search results
and other places in the carousel are white pins with a Maki icon for
their category, black when selected, and their cards drop the number
badge. The icon comes from Search Box's maki name, else the category,
else a plain marker; about 20 common Maki icons (CC0) are inlined.
Numbered badges stay where the number means something: a caller's
numbered label (visit order), optimized stops, start/end.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The cards, summary chip, legend and messages follow the host's theme
(MCP Apps hostContext.theme, at initialize and on host-context-changed),
falling back to prefers-color-scheme. Colors use the host's style
variables (--color-background-primary etc.) when sent, with light/dark
fallbacks otherwise. The map and its pins are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
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.

render_map_tool: bottom carousel for place results on narrow/inline maps

1 participant