import {
Map,
MapSearchControl,
MapTileLayer,
} from "@/components/ui/map"
import type { LatLngExpression } from "leaflet"
export function MapWithSearchControl() {
const TORONTO_COORDINATES = [43.6532, -79.3832] satisfies LatLngExpression
return (
<Map center={TORONTO_COORDINATES}>
<MapTileLayer />
<MapSearchControl />
</Map>
)
}
Accessing Selected Place
You can pass an optional onPlaceSelect callback to the search control to receive the place selected by the user from the autocomplete results.
If you need to perform actions on the map after a place is selected (such as panning, zooming, or adding a marker), you must wrap the search control in a client-side wrapper component because useMap can only be used inside a Map container.
In the example below, a client wrapper component listens for place selection, pans the map to the selected location, and renders a marker.
"use client"
import {
Map,
MapMarker,
MapSearchControl,
MapTileLayer,
} from "@/components/ui/map"
import type { LatLngExpression } from "leaflet"
import { MapPinIcon } from "lucide-react"
import React from "react"
import { useMap } from "react-leaflet"
export function MapWithSearchControlPlaceSelect() {
const TORONTO_COORDINATES = [43.6532, -79.3832] satisfies LatLngExpression
return (
<Map center={TORONTO_COORDINATES}>
<MapTileLayer />
<MapSearchControlWrapper />
</Map>
)
}
function MapSearchControlWrapper() {
const map = useMap()
const [selectedPosition, setSelectedPosition] =
React.useState<LatLngExpression | null>(null)
React.useEffect(() => {
if (!selectedPosition) return
map.panTo(selectedPosition)
}, [selectedPosition])
return (
<>
<MapSearchControl
onPlaceSelect={(feature) =>
setSelectedPosition(
feature.geometry.coordinates.toReversed() as LatLngExpression
)
}
/>
{selectedPosition && (
<MapMarker position={selectedPosition} icon={<MapPinIcon />} />
)}
</>
)
}
Accessing Search Results
You can pass an optional onResultsChange callback to the search control to receive the search results. You can use this callback to access the results and, for example, display markers on the map for each result.
"use client"
import {
Map,
MapMarker,
MapSearchControl,
MapTileLayer,
} from "@/components/ui/map"
import type { PlaceFeature } from "@/components/ui/place-autocomplete"
import type { LatLngExpression } from "leaflet"
import { MapPinIcon } from "lucide-react"
import React from "react"
export function MapWithSearchControlResultsChange() {
const TORONTO_COORDINATES = [43.6532, -79.3832] satisfies LatLngExpression
const [searchResults, setSearchResults] = React.useState<PlaceFeature[]>([])
return (
<Map center={TORONTO_COORDINATES} zoom={2}>
<MapTileLayer />
<MapSearchControl
onResultsChange={(results) => setSearchResults(results)}
/>
{searchResults.map((result) => (
<MapMarker
key={result.properties.osm_id}
position={
result.geometry.coordinates.toReversed() as LatLngExpression
}
icon={<MapPinIcon />}
/>
))}
</Map>
)
}
Search Configurations
You can configure the search using props supported by Shadcn Place Autocomplete, such as limiting the number of results, setting the preferred language, or adjusting other autocomplete behavior.
import {
Map,
MapSearchControl,
MapTileLayer,
} from "@/components/ui/map"
import type { LatLngExpression } from "leaflet"
export function MapWithSearchControlConfigurations() {
const TORONTO_COORDINATES = [43.6532, -79.3832] satisfies LatLngExpression
return (
<Map center={TORONTO_COORDINATES} zoom={2}>
<MapTileLayer />
<MapSearchControl limit={10} lang="en" />
</Map>
)
}