Skip to main content
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

Usage

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..."
    />
  )
}

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

defaultLocation
string
default:"''"
The default location to display
autoDetectOnLoad
boolean
default:"false"
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
className
string
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>
  )
}

Multi-Step Form with Location

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>
  )
}

Header Location Selector

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.

Build docs developers (and LLMs) love