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.
Option | Description | Default |
---|---|---|
resultFormatter | Type: (result: SearchResult) => string ()Function to format search results for display |
|
onSelectResult | Type: (result: SearchResult) => void ()Callback when a search result is selected |
|
maxVisitedLocations | Type: number ()Maximum number of visited locations to display in Timeline.Results |
|
inputRef | Type: RefObject<HTMLInputElement> ()Reference to the search input element |
|
children | Type: ReactNode (required)Search sub-components |
|
Search.Bar
Container for search input and control elements.
Option | Description | Default |
---|---|---|
className | Type: string ()Additional CSS classes |
|
children | Type: ReactNode (required)Search bar elements |
|
Search.Input
The search input field.
Option | Description | Default |
---|---|---|
className | Type: string ()Additional CSS classes |
|
placeholder | Type: string ()Input placeholder text |
|
inputRef | Type: 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).
Option | Description | Default |
---|---|---|
children | Type: 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.
Option | Description | Default |
---|---|---|
children | Type: (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.
Option | Description | Default |
---|---|---|
title | Type: string (required)Group title |
|
className | Type: string ()Additional CSS classes |
|
children | Type: ReactNode (required)Group content |
|
Search.Item
Individual search result item.
Option | Description | Default |
---|---|---|
item | Type: SearchResult (required)Search result data |
|
className | Type: string ()Additional CSS classes |
|
Search.SearchIcon
Icon component specifically designed for the search interface.
Option | Description | Default |
---|---|---|
color | Type: string ()Color of the icon |
|
className | Type: string ()Additional CSS classes |
|
Search.LoadingSpinner
Loading indicator that appears during search operations.
Option | Description | Default |
---|---|---|
className | Type: string ()Additional CSS classes |
|
size | Type: number ()Size of the spinner in pixels |
|
Search.ClearButton
Button to clear the current search input.
Option | Description | Default |
---|---|---|
className | Type: string ()Additional CSS classes |
|
onClick | Type: () => void ()Custom click handler |
|
Search.GeolocateButton
Button that triggers geolocation-based search.
Option | Description | Default |
---|---|---|
id | Type: string ()Button ID |
|
className | Type: string ()Additional CSS classes |
|
onClick | Type: (event: React.MouseEvent) => void ()Custom click handler |
|
icon | Type: IconComponent ()Custom icon component |
|
iconProps | Type: IconProps ()Props passed to the icon |
|
Search.ItemDivider
Horizontal line separator between search items.
Option | Description | Default |
---|---|---|
className | Type: string ()Additional CSS classes |
|
Search.GroupDivider
Horizontal line separator between search groups.
Option | Description | Default |
---|---|---|
className | Type: string ()Additional CSS classes |
|
Search.ScrollableArea
Container component that enables scrolling for search results.
Option | Description | Default |
---|---|---|
children | Type: ReactNode (required)Scrollable content |
|
className | Type: string ()Additional CSS classes |
|
maxHeight | Type: string ()Maximum height of scrollable area |
|