From 1cf8f9444c52d2d12eada19fbfadbb071e93415d Mon Sep 17 00:00:00 2001 From: "nick.leiby" Date: Tue, 25 Aug 2026 23:07:56 -0400 Subject: [PATCH 1/4] Reduce hotspot map clutter Scale hotspot dots by zoom and species count instead of drawing every one at a fixed size, and add a minimum-checklists filter defaulting to hotspots with at least one checklist. Co-Authored-By: Claude Opus 5 (1M context) --- frontend/components/Mapbox.tsx | 17 ++++++++++++-- frontend/hooks/useTrip.ts | 6 +++++ frontend/lib/helpers.ts | 5 +++-- frontend/pages/[tripId]/index.tsx | 37 ++++++++++++++++++++++++++++--- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/frontend/components/Mapbox.tsx b/frontend/components/Mapbox.tsx index 6f655dca..598b7c18 100644 --- a/frontend/components/Mapbox.tsx +++ b/frontend/components/Mapbox.tsx @@ -14,6 +14,7 @@ type Props = { markers?: MarkerT[]; customMarkers?: CustomMarker[]; hotspotLayer?: any; + minChecklists?: number; obsLayer?: any; addingMarker?: boolean; showSatellite?: boolean; @@ -27,6 +28,7 @@ export default function Mapbox({ customMarkers, onHotspotClick, hotspotLayer, + minChecklists = 0, obsLayer, addingMarker, showSatellite, @@ -60,9 +62,20 @@ export default function Mapbox({ const hsLayerStyle = { id: "hotspots", type: "circle", + filter: [">=", ["coalesce", ["get", "checklists"], 0], minChecklists], paint: { - "circle-radius": isMobile ? 8 : 7, - "circle-stroke-width": 0.75, + "circle-radius": [ + "interpolate", + ["linear"], + ["zoom"], + 6, + ["interpolate", ["linear"], ["get", "species"], 0, 1.5, 300, 3.5], + 10, + ["interpolate", ["linear"], ["get", "species"], 0, 3, 300, 6], + 14, + ["interpolate", ["linear"], ["get", "species"], 0, 4.5, 300, isMobile ? 10 : 9], + ], + "circle-stroke-width": ["interpolate", ["linear"], ["zoom"], 6, 0.3, 12, 0.75], "circle-stroke-color": "#555", "circle-color": [ "match", diff --git a/frontend/hooks/useTrip.ts b/frontend/hooks/useTrip.ts index e5d942be..b0bba80f 100644 --- a/frontend/hooks/useTrip.ts +++ b/frontend/hooks/useTrip.ts @@ -27,11 +27,13 @@ type TripUiState = { halo?: HaloT; showAllHotspots: boolean; showSatellite: boolean; + minChecklists: number; setSelectedSpecies: (species?: SelectedSpecies) => void; setSelectedMarkerId: (id?: string) => void; setHalo: (data?: HaloT) => void; setShowAllHotspots: (show: SetState) => void; setShowSatellite: (show: SetState) => void; + setMinChecklists: (min: number) => void; }; const resolve = (value: SetState, prev: T): T => @@ -40,11 +42,13 @@ const resolve = (value: SetState, prev: T): T => const useTripUiStore = create((set) => ({ showAllHotspots: false, showSatellite: false, + minChecklists: 1, setSelectedSpecies: (selectedSpecies) => set({ selectedSpecies }), setSelectedMarkerId: (selectedMarkerId) => set({ selectedMarkerId }), setHalo: (halo) => set({ halo }), setShowAllHotspots: (show) => set((s) => ({ showAllHotspots: resolve(show, s.showAllHotspots) })), setShowSatellite: (show) => set((s) => ({ showSatellite: resolve(show, s.showSatellite) })), + setMinChecklists: (minChecklists) => set({ minChecklists }), })); export const useClearSelectedSpeciesOnNavigate = () => { @@ -105,11 +109,13 @@ export const useTrip = () => { dateRangeLabel, showAllHotspots: ui.showAllHotspots, showSatellite: ui.showSatellite, + minChecklists: ui.minChecklists, setSelectedSpecies: ui.setSelectedSpecies, setSelectedMarkerId: ui.setSelectedMarkerId, setHalo: ui.setHalo, setShowAllHotspots: ui.setShowAllHotspots, setShowSatellite: ui.setShowSatellite, + setMinChecklists: ui.setMinChecklists, refetch, }; }; diff --git a/frontend/lib/helpers.ts b/frontend/lib/helpers.ts index 99435dd7..a273498f 100644 --- a/frontend/lib/helpers.ts +++ b/frontend/lib/helpers.ts @@ -117,8 +117,7 @@ export const getMarkerColor = (count: number) => { if (count <= 250) return markerColors[6]; if (count <= 300) return markerColors[7]; if (count <= 400) return markerColors[8]; - if (count <= 1000) return markerColors[9]; - return markerColors[0]; + return markerColors[9]; }; export const getMarkerColorIndex = (count: number) => { @@ -144,6 +143,8 @@ export const buildHotspotsLayer = ( }, properties: { shade: getMarkerColorIndex(hotspot.species || 0), + species: hotspot.species || 0, + checklists: hotspot.checklists || 0, id: hotspot.id, }, })), diff --git a/frontend/pages/[tripId]/index.tsx b/frontend/pages/[tripId]/index.tsx index fd1ce5f9..6a6cfaeb 100644 --- a/frontend/pages/[tripId]/index.tsx +++ b/frontend/pages/[tripId]/index.tsx @@ -9,13 +9,30 @@ import { useTrip } from "hooks/useTrip"; import MapButton from "components/MapButton"; import MapOverlay from "components/MapOverlay"; import Icon from "components/Icon"; -import { Star, Utensils, MapPin } from "lucide-react"; +import { Star, Utensils, MapPin, Check, Filter } from "lucide-react"; import { Button } from "components/ui/button"; +const CHECKLIST_FILTERS = [ + { label: "All hotspots", value: 0 }, + { label: "1+ checklists", value: 1 }, + { label: "10+ checklists", value: 10 }, + { label: "50+ checklists", value: 50 }, + { label: "100+ checklists", value: 100 }, +]; + export default function Trip() { const { open } = useModal(); - const { trip, canEdit, setSelectedSpecies, showAllHotspots, setShowAllHotspots, showSatellite, setShowSatellite } = - useTrip(); + const { + trip, + canEdit, + setSelectedSpecies, + showAllHotspots, + setShowAllHotspots, + showSatellite, + setShowSatellite, + minChecklists, + setMinChecklists, + } = useTrip(); const [isAddingMarker, setIsAddingMarker] = React.useState(false); const savedHotspots = trip?.hotspots || []; @@ -68,6 +85,19 @@ export default function Trip() { setShowSatellite((prev) => !prev)} tooltip="Satellite view" active={showSatellite}> + {showAllHotspots && ( + 1} + childItems={CHECKLIST_FILTERS.map(({ label, value }) => ({ + label, + onClick: () => setMinChecklists(value), + icon: minChecklists === value ? : , + }))} + > + + + )} {canEdit && ( setIsAddingMarker((prev) => !prev)} @@ -104,6 +134,7 @@ export default function Trip() { markers={markers} customMarkers={customMarkers} hotspotLayer={showAllHotspots && hotspotLayer} + minChecklists={minChecklists} bounds={trip.bounds} addingMarker={isAddingMarker} onDisableAddingMarker={() => setIsAddingMarker(false)} From f719cb5ce65a874e9556006576598bcc7f3c8d3a Mon Sep 17 00:00:00 2001 From: "nick.leiby" Date: Tue, 25 Aug 2026 23:12:45 -0400 Subject: [PATCH 2/4] Scale up hotspot dot sizes Co-Authored-By: Claude Opus 5 (1M context) --- frontend/components/Mapbox.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/components/Mapbox.tsx b/frontend/components/Mapbox.tsx index 598b7c18..57d1c09d 100644 --- a/frontend/components/Mapbox.tsx +++ b/frontend/components/Mapbox.tsx @@ -69,11 +69,11 @@ export default function Mapbox({ ["linear"], ["zoom"], 6, - ["interpolate", ["linear"], ["get", "species"], 0, 1.5, 300, 3.5], + ["interpolate", ["linear"], ["get", "species"], 0, 2.5, 300, 5], 10, - ["interpolate", ["linear"], ["get", "species"], 0, 3, 300, 6], + ["interpolate", ["linear"], ["get", "species"], 0, 4.5, 300, 9], 14, - ["interpolate", ["linear"], ["get", "species"], 0, 4.5, 300, isMobile ? 10 : 9], + ["interpolate", ["linear"], ["get", "species"], 0, 7, 300, isMobile ? 10 : 9], ], "circle-stroke-width": ["interpolate", ["linear"], ["zoom"], 6, 0.3, 12, 0.75], "circle-stroke-color": "#555", From 6d080d7d34406c12afcacd8703465e8b652ea1a9 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 4 Sep 2026 15:30:18 -0700 Subject: [PATCH 3/4] Adjust hotspot filtering UI and tweak sizing --- frontend/components/HotspotFilterMenu.tsx | 78 +++++++++++++++++++ frontend/components/Mapbox.tsx | 27 +++++-- frontend/components/MinStepper.tsx | 39 ++++++++++ frontend/components/SpeciesHotspotToolbar.tsx | 42 ++-------- frontend/hooks/useTrip.ts | 19 +++-- frontend/lib/icons.ts | 4 + frontend/pages/[tripId]/index.tsx | 37 ++------- 7 files changed, 166 insertions(+), 80 deletions(-) create mode 100644 frontend/components/HotspotFilterMenu.tsx create mode 100644 frontend/components/MinStepper.tsx diff --git a/frontend/components/HotspotFilterMenu.tsx b/frontend/components/HotspotFilterMenu.tsx new file mode 100644 index 00000000..1052e382 --- /dev/null +++ b/frontend/components/HotspotFilterMenu.tsx @@ -0,0 +1,78 @@ +import React from "react"; +import { cn } from "lib/utils"; +import Icon from "components/Icon"; +import MapButton from "components/MapButton"; +import MinStepper from "components/MinStepper"; +import { Button } from "components/ui/button"; +import { Switch } from "components/ui/switch"; +import { useTrip, DEFAULT_HOTSPOT_FILTERS } from "hooks/useTrip"; + +const MIN_CHECKLIST_STEPS = [0, 1, 5, 10, 25, 50, 100, 250, 500, 1000]; +const MIN_SPECIES_STEPS = [0, 25, 50, 100, 150, 200, 250, 300, 400]; + +export default function HotspotFilterMenu() { + const { showAllHotspots, setShowAllHotspots, hotspotFilters, setHotspotFilters } = useTrip(); + const [open, setOpen] = React.useState(false); + const { minChecklists, minSpecies } = hotspotFilters; + const activeCount = + (showAllHotspots ? 0 : 1) + + (minChecklists !== DEFAULT_HOTSPOT_FILTERS.minChecklists ? 1 : 0) + + (minSpecies !== DEFAULT_HOTSPOT_FILTERS.minSpecies ? 1 : 0); + + return ( +
+ setOpen((o) => !o)} tooltip={open ? undefined : "Hotspots"} active={showAllHotspots}> + + + {open && ( + <> +
setOpen(false)} className="fixed inset-0 z-30" /> +
+
+
Filters
+ +
+ +
+
+ Minimum checklists +
+
+ setHotspotFilters({ minChecklists })} + steps={MIN_CHECKLIST_STEPS} + min={0} + /> +
+
+ Minimum species +
+ setHotspotFilters({ minSpecies })} + steps={MIN_SPECIES_STEPS} + min={0} + /> +
+
+ + )} +
+ ); +} diff --git a/frontend/components/Mapbox.tsx b/frontend/components/Mapbox.tsx index 57d1c09d..6dabc3d2 100644 --- a/frontend/components/Mapbox.tsx +++ b/frontend/components/Mapbox.tsx @@ -7,14 +7,14 @@ import { markerColors, getLatLngFromBounds } from "lib/helpers"; import MarkerWithIcon from "components/MarkerWithIcon"; import clsx from "clsx"; import { useModal } from "stores/modals"; -import { useTrip } from "hooks/useTrip"; +import { useTrip, HotspotFilters, DEFAULT_HOTSPOT_FILTERS } from "hooks/useTrip"; type Props = { bounds: Trip["bounds"]; markers?: MarkerT[]; customMarkers?: CustomMarker[]; hotspotLayer?: any; - minChecklists?: number; + hotspotFilters?: HotspotFilters; obsLayer?: any; addingMarker?: boolean; showSatellite?: boolean; @@ -28,7 +28,7 @@ export default function Mapbox({ customMarkers, onHotspotClick, hotspotLayer, - minChecklists = 0, + hotspotFilters = DEFAULT_HOTSPOT_FILTERS, obsLayer, addingMarker, showSatellite, @@ -59,20 +59,33 @@ export default function Mapbox({ return window.innerWidth < 768; }, []); + const visibleHotspotCount = (hotspotLayer?.features || []).filter( + (f: any) => + f.properties.checklists >= hotspotFilters.minChecklists && + f.properties.species >= hotspotFilters.minSpecies + ).length; + const isSparse = visibleHotspotCount < 50; + const hsLayerStyle = { id: "hotspots", type: "circle", - filter: [">=", ["coalesce", ["get", "checklists"], 0], minChecklists], + filter: [ + "all", + [">=", ["get", "checklists"], hotspotFilters.minChecklists], + [">=", ["get", "species"], hotspotFilters.minSpecies], + ], paint: { "circle-radius": [ "interpolate", ["linear"], ["zoom"], 6, - ["interpolate", ["linear"], ["get", "species"], 0, 2.5, 300, 5], - 10, + isSparse + ? ["interpolate", ["linear"], ["get", "species"], 0, 3.5, 300, 7] + : ["interpolate", ["linear"], ["get", "species"], 0, 3, 300, 5], + 9, ["interpolate", ["linear"], ["get", "species"], 0, 4.5, 300, 9], - 14, + 12, ["interpolate", ["linear"], ["get", "species"], 0, 7, 300, isMobile ? 10 : 9], ], "circle-stroke-width": ["interpolate", ["linear"], ["zoom"], 6, 0.3, 12, 0.75], diff --git a/frontend/components/MinStepper.tsx b/frontend/components/MinStepper.tsx new file mode 100644 index 00000000..792989a7 --- /dev/null +++ b/frontend/components/MinStepper.tsx @@ -0,0 +1,39 @@ +import { Button } from "components/ui/button"; + +type Props = { + value: number; + onChange: (n: number) => void; + steps: number[]; + min: number; +}; + +export default function MinStepper({ value, onChange, steps, min }: Props) { + const next = steps.find((s) => s > value) ?? value + 100; + const below = steps.filter((s) => s < value); + const prev = below.length > 0 ? below[below.length - 1] : Math.max(min, value - 100); + + return ( +
+ Min + + {value} + +
+ ); +} diff --git a/frontend/components/SpeciesHotspotToolbar.tsx b/frontend/components/SpeciesHotspotToolbar.tsx index 71329dde..1cade1ad 100644 --- a/frontend/components/SpeciesHotspotToolbar.tsx +++ b/frontend/components/SpeciesHotspotToolbar.tsx @@ -4,6 +4,8 @@ import Icon from "components/Icon"; import SelectDropdown from "components/SelectDropdown"; import SegmentedControl from "components/SegmentedControl"; import FilterChip from "components/FilterChip"; +import MinStepper from "components/MinStepper"; +import { Button } from "components/ui/button"; export type Scope = "saved" | "all"; export type SortKey = "best" | "freq"; @@ -15,17 +17,6 @@ const SORT_OPTIONS: { value: SortKey; label: string }[] = [ const MIN_OBS_STEPS = [1, 2, 5, 10, 25, 50, 100, 200, 300, 400]; -function nextStep(n: number): number { - const found = MIN_OBS_STEPS.find((s) => s > n); - return found ?? n + 100; -} - -function prevStep(n: number): number { - const below = MIN_OBS_STEPS.filter((s) => s < n); - if (below.length > 0) return below[below.length - 1]; - return Math.max(1, n - 100); -} - type Props = { scope: Scope; setScope: (s: Scope) => void; @@ -102,17 +93,17 @@ function MoreFiltersMenu({
Last seen (days)
- +
Minimum observations -
- Min - - {minObservations} - -
+ )} diff --git a/frontend/hooks/useTrip.ts b/frontend/hooks/useTrip.ts index b0bba80f..9377e2dc 100644 --- a/frontend/hooks/useTrip.ts +++ b/frontend/hooks/useTrip.ts @@ -21,19 +21,26 @@ type HaloT = { type SetState = T | ((prev: T) => T); +export type HotspotFilters = { + minChecklists: number; + minSpecies: number; +}; + +export const DEFAULT_HOTSPOT_FILTERS: HotspotFilters = { minChecklists: 0, minSpecies: 0 }; + type TripUiState = { selectedSpecies?: SelectedSpecies; selectedMarkerId?: string; halo?: HaloT; showAllHotspots: boolean; showSatellite: boolean; - minChecklists: number; + hotspotFilters: HotspotFilters; setSelectedSpecies: (species?: SelectedSpecies) => void; setSelectedMarkerId: (id?: string) => void; setHalo: (data?: HaloT) => void; setShowAllHotspots: (show: SetState) => void; setShowSatellite: (show: SetState) => void; - setMinChecklists: (min: number) => void; + setHotspotFilters: (filters: Partial) => void; }; const resolve = (value: SetState, prev: T): T => @@ -42,13 +49,13 @@ const resolve = (value: SetState, prev: T): T => const useTripUiStore = create((set) => ({ showAllHotspots: false, showSatellite: false, - minChecklists: 1, + hotspotFilters: DEFAULT_HOTSPOT_FILTERS, setSelectedSpecies: (selectedSpecies) => set({ selectedSpecies }), setSelectedMarkerId: (selectedMarkerId) => set({ selectedMarkerId }), setHalo: (halo) => set({ halo }), setShowAllHotspots: (show) => set((s) => ({ showAllHotspots: resolve(show, s.showAllHotspots) })), setShowSatellite: (show) => set((s) => ({ showSatellite: resolve(show, s.showSatellite) })), - setMinChecklists: (minChecklists) => set({ minChecklists }), + setHotspotFilters: (filters) => set((s) => ({ hotspotFilters: { ...s.hotspotFilters, ...filters } })), })); export const useClearSelectedSpeciesOnNavigate = () => { @@ -109,13 +116,13 @@ export const useTrip = () => { dateRangeLabel, showAllHotspots: ui.showAllHotspots, showSatellite: ui.showSatellite, - minChecklists: ui.minChecklists, + hotspotFilters: ui.hotspotFilters, setSelectedSpecies: ui.setSelectedSpecies, setSelectedMarkerId: ui.setSelectedMarkerId, setHalo: ui.setHalo, setShowAllHotspots: ui.setShowAllHotspots, setShowSatellite: ui.setShowSatellite, - setMinChecklists: ui.setMinChecklists, + setHotspotFilters: ui.setHotspotFilters, refetch, }; }; diff --git a/frontend/lib/icons.ts b/frontend/lib/icons.ts index 6a540b28..af1826ae 100644 --- a/frontend/lib/icons.ts +++ b/frontend/lib/icons.ts @@ -167,6 +167,10 @@ export const icons = { viewbox: "0 0 640 512", path: "M96 128a128 128 0 1 1 256 0A128 128 0 1 1 96 128zM0 482.3C0 383.8 79.8 304 178.3 304h91.4C368.2 304 448 383.8 448 482.3c0 16.4-13.3 29.7-29.7 29.7H29.7C13.3 512 0 498.7 0 482.3zM504 312V248H440c-13.3 0-24-10.7-24-24s10.7-24 24-24h64V136c0-13.3 10.7-24 24-24s24 10.7 24 24v64h64c13.3 0 24 10.7 24 24s-10.7 24-24 24H552v64c0 13.3-10.7 24-24 24s-24-10.7-24-24z", }, + sliders: { + viewbox: "0 0 640 640", + path: "M88 136C74.7 136 64 146.7 64 160C64 173.3 74.7 184 88 184L179.7 184C189.9 216.5 220.2 240 256 240C291.8 240 322.1 216.5 332.3 184L552 184C565.3 184 576 173.3 576 160C576 146.7 565.3 136 552 136L332.3 136C322.1 103.5 291.8 80 256 80C220.2 80 189.9 103.5 179.7 136L88 136zM88 296C74.7 296 64 306.7 64 320C64 333.3 74.7 344 88 344L339.7 344C349.9 376.5 380.2 400 416 400C451.8 400 482.1 376.5 492.3 344L552 344C565.3 344 576 333.3 576 320C576 306.7 565.3 296 552 296L492.3 296C482.1 263.5 451.8 240 416 240C380.2 240 349.9 263.5 339.7 296L88 296zM88 456C74.7 456 64 466.7 64 480C64 493.3 74.7 504 88 504L147.7 504C157.9 536.5 188.2 560 224 560C259.8 560 290.1 536.5 300.3 504L552 504C565.3 504 576 493.3 576 480C576 466.7 565.3 456 552 456L300.3 456C290.1 423.5 259.8 400 224 400C188.2 400 157.9 423.5 147.7 456L88 456zM224 512C206.3 512 192 497.7 192 480C192 462.3 206.3 448 224 448C241.7 448 256 462.3 256 480C256 497.7 241.7 512 224 512zM416 352C398.3 352 384 337.7 384 320C384 302.3 398.3 288 416 288C433.7 288 448 302.3 448 320C448 337.7 433.7 352 416 352zM224 160C224 142.3 238.3 128 256 128C273.7 128 288 142.3 288 160C288 177.7 273.7 192 256 192C238.3 192 224 177.7 224 160z", + }, speaker: { viewbox: "0 0 576 512", path: "M333.1 34.8C344.6 40 352 51.4 352 64V448c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L163.8 352H96c-35.3 0-64-28.7-64-64V224c0-35.3 28.7-64 64-64h67.8L298.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3zm172 72.2c43.2 35.2 70.9 88.9 70.9 149s-27.7 113.8-70.9 149c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C507.3 341.3 528 301.1 528 256s-20.7-85.3-53.2-111.8c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zm-60.5 74.5C466.1 199.1 480 225.9 480 256s-13.9 56.9-35.4 74.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C425.1 284.4 432 271 432 256s-6.9-28.4-17.7-37.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5z", diff --git a/frontend/pages/[tripId]/index.tsx b/frontend/pages/[tripId]/index.tsx index 6a6cfaeb..9c68e7f6 100644 --- a/frontend/pages/[tripId]/index.tsx +++ b/frontend/pages/[tripId]/index.tsx @@ -9,17 +9,10 @@ import { useTrip } from "hooks/useTrip"; import MapButton from "components/MapButton"; import MapOverlay from "components/MapOverlay"; import Icon from "components/Icon"; -import { Star, Utensils, MapPin, Check, Filter } from "lucide-react"; +import HotspotFilterMenu from "components/HotspotFilterMenu"; +import { Star, Utensils, MapPin } from "lucide-react"; import { Button } from "components/ui/button"; -const CHECKLIST_FILTERS = [ - { label: "All hotspots", value: 0 }, - { label: "1+ checklists", value: 1 }, - { label: "10+ checklists", value: 10 }, - { label: "50+ checklists", value: 50 }, - { label: "100+ checklists", value: 100 }, -]; - export default function Trip() { const { open } = useModal(); const { @@ -30,8 +23,7 @@ export default function Trip() { setShowAllHotspots, showSatellite, setShowSatellite, - minChecklists, - setMinChecklists, + hotspotFilters, } = useTrip(); const [isAddingMarker, setIsAddingMarker] = React.useState(false); @@ -75,29 +67,10 @@ export default function Trip() { <> {trip && {`${trip.name} | BirdPlan.app`}}
- setShowAllHotspots((prev) => !prev)} - tooltip={showAllHotspots ? "Hide hotspots" : "Show hotspots"} - active={showAllHotspots} - > - - + setShowSatellite((prev) => !prev)} tooltip="Satellite view" active={showSatellite}> - {showAllHotspots && ( - 1} - childItems={CHECKLIST_FILTERS.map(({ label, value }) => ({ - label, - onClick: () => setMinChecklists(value), - icon: minChecklists === value ? : , - }))} - > - - - )} {canEdit && ( setIsAddingMarker((prev) => !prev)} @@ -134,7 +107,7 @@ export default function Trip() { markers={markers} customMarkers={customMarkers} hotspotLayer={showAllHotspots && hotspotLayer} - minChecklists={minChecklists} + hotspotFilters={hotspotFilters} bounds={trip.bounds} addingMarker={isAddingMarker} onDisableAddingMarker={() => setIsAddingMarker(false)} From 45ea31f3964b8c5913dc9e51365bf4baf6d6ca81 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 4 Sep 2026 15:33:30 -0700 Subject: [PATCH 4/4] Update HotspotFilterMenu.tsx --- frontend/components/HotspotFilterMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/components/HotspotFilterMenu.tsx b/frontend/components/HotspotFilterMenu.tsx index 1052e382..9429d30f 100644 --- a/frontend/components/HotspotFilterMenu.tsx +++ b/frontend/components/HotspotFilterMenu.tsx @@ -21,7 +21,7 @@ export default function HotspotFilterMenu() { return (
- setOpen((o) => !o)} tooltip={open ? undefined : "Hotspots"} active={showAllHotspots}> + setOpen((o) => !o)} tooltip={open ? undefined : "Hotspots"} active={activeCount > 0}> {open && (