Skip to Content
ExamplesAdd a search bar

Maps UI SDK - Adding a Search Bar

This example demonstrates how to add a search bar to your application using the Search component. Search provides autocomplete location suggestions through the Places API, keyboard navigation, customizable styling and more.

Key Features

  • Autocomplete location search
  • Keyboard navigation support
  • Accessible combobox pattern
  • Customizable styling
  • Loading and clear states

Implementation

  1. Create a formatter function for search results:
const formatResult = (result: WeatherPlaceSearchResult) => { if ('place' in result) { const { place } = result; const parts = [ place.name, place.state ? place.state.toUpperCase() : null, place.country === 'US' ? null : place.countryFull ].filter(Boolean); return parts.join(', '); } return ''; };
  1. Create the search bar component with an input field, loading spinner, and clear button:
import { Search } from '@xweather/maps-ui-sdk'; const SearchBar = () => ( <Search.Bar className="bg-white rounded-lg shadow-lg px-2 py-1 gap-2"> <Search.SearchIcon className="text-slate-500" /> <Search.Input placeholder="Search locations" className="px-1 py-0.5 bg-white selection:bg-[#AAF0E4]" /> <Search.LoadingSpinner /> <Search.Clear /> </Search.Bar> );
  1. Create the search results component:
import { Search } from '@xweather/maps-ui-sdk'; const SearchResults = () => ( <Search.ResultsFetcher> <Search.ResultsData> {({ hasResults }) => ( hasResults ? ( <Search.List> <Search.ScrollableArea className="py-4 mt-2 bg-white rounded-lg shadow-lg"> <SearchItems /> </Search.ScrollableArea> </Search.List> ) : null )} </Search.ResultsData> </Search.ResultsFetcher> );
  1. Create the search items component to render individual results:
import { Search, useSearchContext } from '@xweather/maps-ui-sdk'; const SearchItems = () => { const { currentResults, activeDescendantId } = useSearchContext(); return currentResults.map((result, index) => ( <> {index > 0 && ( <Search.Divider className="border-slate-300" /> )} <Search.Item item={result}> <Search.ItemButton className={`px-4 py-1.5 text-sm ${ activeDescendantId === result.trackingId ? 'text-white bg-[#3ABBA3]' : 'text-black' }`} /> </Search.Item> </> )); };

The activeDescendantId matches the trackingId of the currently active/focused result, allowing you to style items based on keyboard navigation or hover state. This implements the ARIA combobox pattern  for accessibility.

  1. Finally, combine everything into a LocationSearch component:
import { Search } from '@xweather/maps-ui-sdk'; import { type WeatherPlaceSearchResult } from '@xweather/maps-ui-sdk/dist/types/search'; const handleSelectResult = (result: WeatherPlaceSearchResult) => { const { lat, long } = result.loc; // You can use these coordinates to update your map view // See the 'Add a map controller with controls' example for setting up the map }; export const LocationSearch = () => ( <Search onSelectResult={handleSelectResult} searchGroups={['places']} // Can also include 'stations' and 'recent' resultFormatter={formatResult} > <Search.FocusArea className="w-80"> <SearchBar /> <SearchResults /> </Search.FocusArea> </Search> );

The searchGroups prop can accept an array of different search types:

  • 'places': Location search results
  • 'stations': Weather station results
  • 'recent': Recently viewed locations

Combine this with the Map Controller example to see a complete example of integrating this search component with a map.

© 2026 Xweather (opens in a new tab)Terms of Service (opens in a new tab)Privacy Policy (opens in a new tab)