Components
Search

Search

The Search compound component provides a flexible, composable interface for location-based searching.

Features

  • Text-based location search
  • Geolocation
  • Recent search history
  • Grouped search results (Cities/Places)
  • Loading states
  • Custom result formatting

Usage Examples

Basic Search Implementation

import { Search } from '@xweather/map-ui-sdk';
 
const SearchExample = () => {
  const handleSelectResult = (result) => {
    const { lat, long } = result.loc;
    // Handle the selected location
  };
 
  return (
    <Search onSelectResult={handleSelectResult}>
      <Search.Bar>
        <Search.SearchIcon />
        <Search.Input placeholder="Search for a location" />
        <Search.LoadingSpinner />
        <Search.ClearButton />
        <Search.GeolocateButton />
      </Search.Bar>
      <Search.ResultsFetcher>
        <Search.ResultsData>
          {({ results, visitedLocations, hasResults }) => (
            <Search.ScrollableArea>
              {visitedLocations.length > 0 && (
                <Search.Group title="Recent">
                  {visitedLocations.map((item) => (
                    <Search.Item key={item.id} item={item} />
                  ))}
                </Search.Group>
              )}
              {hasResults && (
                <>
                  <Search.Group title="Cities">
                    {results
                      .filter((item) => item.type === 'city')
                      .map((item) => (
                        <Search.Item key={item.id} item={item} />
                      ))}
                  </Search.Group>
                  <Search.Group title="Places">
                    {results
                      .filter((item) => item.type === 'place')
                      .map((item) => (
                        <Search.Item key={item.id} item={item} />
                      ))}
                  </Search.Group>
                </>
              )}
            </Search.ScrollableArea>
          )}
        </Search.ResultsData>
      </Search.ResultsFetcher>
    </Search>
  );
};

Interactive Search with Tabs

Here's an example of integrating the Search component within a tabbed interface:

import { useEffect, useState, useRef } from 'react';
import { Search } from '@xweather/map-ui-sdk';
import { Tabs } from '@xweather/map-ui-sdk/components/tabs';
 
const TabbedSearch = () => {
  const [currentTab, setCurrentTab] = useState<string | null>(null);
  const searchInputRef = useRef<HTMLInputElement>(null);
  const [coordinates, setCoordinates] = useState<{ lat: number; lon: number } | null>(null);
 
  // Auto-focus search input when tab is selected
  useEffect(() => {
    if (currentTab === 'search') {
      searchInputRef.current?.focus();
    }
  }, [currentTab]);
 
  const handleSelectResult = (result) => {
    const { lat, long } = result.loc;
    setCoordinates({ lat, lon: long });
  };
 
  return (
    <Tabs.Provider value={currentTab} onChange={setCurrentTab}>
      <Tabs.List>
        <Tabs.Button value="search">Search Tab</Tabs.Button>
        <Tabs.Button value="settings">Settings Tab</Tabs.Button>
      </Tabs.List>
 
      <Tabs.Content value="search">
        <Search
          className="sm:w-90"
          inputRef={searchInputRef}
          onSelectResult={handleSelectResult}
        >
          <Search.Bar>
            <Search.SearchIcon />
            <Search.Input />
            <Search.LoadingSpinner />
            <Search.ClearButton />
            <Search.GeolocateButton />
          </Search.Bar>
          <Search.ResultsFetcher>
            <Search.ResultsData>
              {/* Results rendering */}
            </Search.ResultsData>
          </Search.ResultsFetcher>
        </Search>
      </Tabs.Content>
    </Tabs.Provider>
  );
};

Custom Result Formatting

You can customize how search results are displayed by providing a resultFormatter function:

const customFormatter = (result: SearchResult) => {
  if (result.type === 'city') {
    return `${result.name}, ${result.admin1}, ${result.country}`;
  }
  return `${result.name} (${result.type})`;
};
 
const SearchWithCustomFormat = () => (
  <Search resultFormatter={customFormatter}>
    {/* Search components */}
  </Search>
);

API Reference

Search (Root)

The main wrapper component that provides search context to all child components.

OptionDescriptionDefault
resultFormatterType: (result: SearchResult) => string ()Function to format search results for displayformatResult
onSelectResultType: (result: SearchResult) => void ()Callback when a search result is selected
maxVisitedLocationsType: number ()Maximum number of visited locations to display in Timeline.Results3
inputRefType: RefObject<HTMLInputElement> ()Reference to the search input element
childrenType: ReactNode (required)Search sub-components

Search.Bar

Container for search input and control elements.

OptionDescriptionDefault
classNameType: string ()Additional CSS classes
childrenType: ReactNode (required)Search bar elements

Search.Input

The search input field.

OptionDescriptionDefault
classNameType: string ()Additional CSS classes
placeholderType: string ()Input placeholder textSearch locations
inputRefType: RefObject<HTMLInputElement> ()Reference to the search input element

Search.ResultsFetcher

A wrapper component that handles data fetching from the XWeather Weather API places endpoint (opens in a new tab).

OptionDescriptionDefault
childrenType: ReactNode (required)Components that need access to the fetched data

Search.ResultsData

A component that processes and provides search results data to its children through a render prop pattern. It manages both API search results and visited (recent) locations, transforming raw API responses into a consumable format.

OptionDescriptionDefault
childrenType: (props: { results: SearchResult[], visitedLocations: SearchResult[], hasResults: boolean }) => ReactNode (required)Render prop function that receives the processed search results, visited locations, and a boolean indicating if there are any results to display

Search.Group

Groups search results with a title.

OptionDescriptionDefault
titleType: string (required)Group title
classNameType: string ()Additional CSS classes
childrenType: ReactNode (required)Group content

Search.Item

Individual search result item.

OptionDescriptionDefault
itemType: SearchResult (required)Search result data
classNameType: string ()Additional CSS classes

Search.SearchIcon

Icon component specifically designed for the search interface.

OptionDescriptionDefault
colorType: string ()Color of the icon'none'
classNameType: string ()Additional CSS classes

Search.LoadingSpinner

Loading indicator that appears during search operations.

OptionDescriptionDefault
classNameType: string ()Additional CSS classes
sizeType: number ()Size of the spinner in pixels16

Search.ClearButton

Button to clear the current search input.

OptionDescriptionDefault
classNameType: string ()Additional CSS classes
onClickType: () => void ()Custom click handler

Search.GeolocateButton

Button that triggers geolocation-based search.

OptionDescriptionDefault
idType: string ()Button ID'search-geolocate-button'
classNameType: string ()Additional CSS classes
onClickType: (event: React.MouseEvent) => void ()Custom click handler
iconType: IconComponent ()Custom icon componentGeoLocateIcon
iconPropsType: IconProps ()Props passed to the icon

Search.ItemDivider

Horizontal line separator between search items.

OptionDescriptionDefault
classNameType: string ()Additional CSS classes

Search.GroupDivider

Horizontal line separator between search groups.

OptionDescriptionDefault
classNameType: string ()Additional CSS classes

Search.ScrollableArea

Container component that enables scrolling for search results.

OptionDescriptionDefault
childrenType: ReactNode (required)Scrollable content
classNameType: string ()Additional CSS classes
maxHeightType: string ()Maximum height of scrollable area