From 36021deb79ddbda12019c1921c6b8d21ed6fbd99 Mon Sep 17 00:00:00 2001 From: Sajid Mehmood Date: Thu, 16 Jul 2026 13:12:31 +0000 Subject: [PATCH] Add click-to-filter on world map countries Clicking a country on the world map now toggles a country=eq.XX URL filter, scoping all metrics on the page to that country via the existing filter system. The active country is highlighted with the primary color and a pointer cursor. Reuses useNavigation/updateParams so the shared FilterBar picks up the filter. Only enabled when a websiteId is present (the realtime map uses raw data and stays non-interactive). Uses onClick rather than onMouseDown/onMouseUp because d3-zoom in ZoomableGroup intercepts mouseup on the SVG and blocks React's synthetic handler; click also naturally does not fire after a drag-pan, so panning the map will not trigger a filter. --- src/components/metrics/WorldMap.tsx | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/components/metrics/WorldMap.tsx b/src/components/metrics/WorldMap.tsx index 3c8fadb80..3297fa6be 100644 --- a/src/components/metrics/WorldMap.tsx +++ b/src/components/metrics/WorldMap.tsx @@ -6,6 +6,7 @@ import { useCountryNames, useLocale, useMessages, + useNavigation, useWebsiteMetricsQuery, } from '@/components/hooks'; import { getThemeColors } from '@/lib/colors'; @@ -25,6 +26,7 @@ export function WorldMap({ websiteId, data, ...props }: WorldMapProps) { const { locale } = useLocale(); const { formatMessage, labels } = useMessages(); const { countryNames } = useCountryNames(locale); + const { router, updateParams, query } = useNavigation(); const visitorsLabel = formatMessage(labels.visitors).toLocaleLowerCase(locale); const unknownLabel = formatMessage(labels.unknown); @@ -64,6 +66,16 @@ export function WorldMap({ websiteId, data, ...props }: WorldMapProps) { ); }; + const isInteractive = (code: string) => !!websiteId && code !== 'AQ'; + + const isActive = (code: string) => query.country === `eq.${code}`; + + const handleClick = (code: string) => { + if (!isInteractive(code)) return; + const isSelected = isActive(code); + router.replace(updateParams({ country: isSelected ? undefined : `eq.${code}` })); + }; + return ( { return geographies.map(geo => { const code = ISO_COUNTRIES[geo.id]; + const interactive = isInteractive(code); + const active = isActive(code); return ( handleHover(code)} onMouseOut={() => setTooltipPopup(null)} + onClick={interactive ? () => handleClick(code) : undefined} /> ); });