A powerful location search and selection component with autocomplete suggestions, geolocation support, and two display variants. Available for both Web and React Native platforms.
Installation
npx shadcn@latest add https://rigidui.com/r/location-picker.json
Prerequisites Ensure you have React Native Reusables properly set up. Follow the React Native Reusables Installation guide. Install Dependencies npx expo install expo-device expo-location
Add the expo-location plugin to your app.json: {
"expo" : {
"plugins" : [ "expo-location" ]
}
}
For additional configuration options, see Expo Location docs . Install Component npx shadcn@latest add https://rigidui.com/r/location-picker-rn.json
Usage
Popover Variant
Inline Variant
Auto-Detect
React Native
import { LocationPicker } from "@/components/location-picker"
import { useState } from "react"
export default function App () {
const [ location , setLocation ] = useState ( "" )
return (
< LocationPicker
variant = "popover"
onChange = { setLocation }
placeholder = "Select your city..."
/>
)
}
import { LocationPicker } from "@/components/location-picker"
function LocationForm () {
return (
< form >
< label > Delivery Location </ label >
< LocationPicker
variant = "inline"
defaultLocation = "New York"
onChange = { ( location ) => console . log ( 'Selected:' , location ) }
placeholder = "Enter city, district, or area"
/>
</ form >
)
}
import { LocationPicker } from "@/components/location-picker"
function AutoDetectLocation () {
return (
< LocationPicker
variant = "popover"
autoDetectOnLoad = { true }
onChange = { ( location ) => {
// Save to state or localStorage
localStorage . setItem ( 'userLocation' , location )
} }
/>
)
}
import { LocationPicker } from "@/components/location-picker-rn"
import { useState } from "react"
import { View , Text } from "react-native"
export default function LocationScreen () {
const [ selectedLocation , setSelectedLocation ] = useState ( "" )
return (
< View className = "p-4" >
< Text className = "text-lg mb-2" > Select Location </ Text >
< LocationPicker
variant = "popover"
onChange = { setSelectedLocation }
placeholder = "Tap to search locations..."
/>
{ selectedLocation && (
< Text className = "mt-2" > Selected: { selectedLocation } </ Text >
) }
</ View >
)
}
Features
Location Search Users can search for locations by name, address, or postal code with real-time suggestions.
Dual Variants Choose between popover variant for compact layouts or inline variant for full-featured forms.
Autocomplete Suggestions As users type, the component provides autocomplete suggestions with debounced search.
Cross-Platform Available for both Web and React Native with platform-specific optimizations.
Geolocation Support Quickly use current location with browser geolocation API or native location services.
OpenStreetMap Integration Powered by OpenStreetMap’s Nominatim API for accurate, free location data.
API Reference
LocationPicker
The default location to display
Whether to automatically detect location on component load
variant
'popover' | 'inline'
default: "'popover'"
The display variant of the component
placeholder
string
default: "'Enter city, district, or area'"
Placeholder text for the search input
onChange
(location: string) => void
Callback function called when location changes
Additional class names for styling
Examples
E-commerce Location Selector
import { LocationPicker } from "@/components/location-picker"
import { useState , useEffect } from "react"
function DeliveryLocationSelector () {
const [ location , setLocation ] = useState ( "" )
const [ availableStores , setAvailableStores ] = useState ([])
useEffect (() => {
if ( location ) {
// Fetch nearby stores
fetchStoresByLocation ( location ). then ( setAvailableStores )
}
}, [ location ])
return (
< div className = "space-y-4" >
< div >
< label className = "text-sm font-medium" > Delivery Location </ label >
< LocationPicker
variant = "inline"
placeholder = "Search your area..."
onChange = { setLocation }
autoDetectOnLoad = { true }
/>
</ div >
{ availableStores . length > 0 && (
< div >
< p className = "text-sm text-muted-foreground" >
{ availableStores . length } stores nearby
</ p >
</ div >
) }
</ div >
)
}
import { LocationPicker } from "@/components/location-picker"
import { Button } from "@/components/ui/button"
function RegistrationForm () {
const [ formData , setFormData ] = useState ({
name: '' ,
email: '' ,
location: ''
})
const handleSubmit = ( e ) => {
e . preventDefault ()
console . log ( 'Form data:' , formData )
}
return (
< form onSubmit = { handleSubmit } className = "space-y-4" >
< input
type = "text"
placeholder = "Name"
value = { formData . name }
onChange = { ( e ) => setFormData ({ ... formData , name: e . target . value }) }
/>
< input
type = "email"
placeholder = "Email"
value = { formData . email }
onChange = { ( e ) => setFormData ({ ... formData , email: e . target . value }) }
/>
< div >
< label > Location </ label >
< LocationPicker
variant = "inline"
onChange = { ( location ) => setFormData ({ ... formData , location }) }
/>
</ div >
< Button type = "submit" disabled = { ! formData . location } >
Submit
</ Button >
</ form >
)
}
import { LocationPicker } from "@/components/location-picker"
function Header () {
return (
< header className = "flex items-center justify-between p-4 border-b" >
< div className = "logo" > MyApp </ div >
< LocationPicker
variant = "popover"
defaultLocation = { getStoredLocation () }
onChange = { ( location ) => {
localStorage . setItem ( 'userLocation' , location )
// Trigger location-based content update
} }
className = "mx-4"
/>
< nav > ... </ nav >
</ header >
)
}
function getStoredLocation () {
return localStorage . getItem ( 'userLocation' ) || ''
}
Service Area Validator
import { LocationPicker } from "@/components/location-picker"
import { useState } from "react"
function ServiceAreaCheck () {
const [ location , setLocation ] = useState ( "" )
const [ isServiceable , setIsServiceable ] = useState ( null )
const serviceableAreas = [ 'New York' , 'Los Angeles' , 'Chicago' , 'Houston' ]
const handleLocationChange = ( selectedLocation ) => {
setLocation ( selectedLocation )
const serviceable = serviceableAreas . some ( area =>
selectedLocation . toLowerCase (). includes ( area . toLowerCase ())
)
setIsServiceable ( serviceable )
}
return (
< div className = "space-y-4" >
< LocationPicker
variant = "inline"
onChange = { handleLocationChange }
placeholder = "Enter your location"
/>
{ isServiceable !== null && (
< div className = { isServiceable ? 'text-green-600' : 'text-red-600' } >
{ isServiceable
? '✓ We deliver to your area!'
: '✗ Sorry, we don \' t serve this area yet.' }
</ div >
) }
</ div >
)
}
The component uses OpenStreetMap’s Nominatim API which is free but has rate limits. For production use with high traffic, consider implementing your own location API or caching mechanism.
The inline variant displays the search input and suggestions directly in the page flow, while the popover variant shows them in a compact popover overlay.
When using geolocation, always handle permission denials gracefully and provide alternative manual search options.