React Components
Complete reference for all React components in the Seekora UI SDK.
SearchProvider
The root component that provides context to all child components.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
client | SeekoraClient | Required | Seekora client instance |
theme | ThemeConfig | - | Custom theme configuration |
enableAnalytics | boolean | true | Enable/disable analytics |
autoTrackSearch | boolean | true | Auto-track search events |
stateManager | SearchStateManagerConfig | - | State manager config |
children | ReactNode | Required | Child components |
Example
import { SeekoraClient } from '@seekora-ai/search-sdk';
import { SearchProvider } from '@seekora-ai/ui-sdk-react';
const client = new SeekoraClient({
storeId: 'your-store-id',
readSecret: 'your-read-secret',
});
function App() {
return (
<SearchProvider
client={client}
enableAnalytics={true}
autoTrackSearch={true}
>
{/* Child components */}
</SearchProvider>
);
}
SearchBar
Interactive search input with integrated query suggestions.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | "Search..." | Input placeholder |
showSuggestions | boolean | true | Show suggestions dropdown |
debounceMs | number | 300 | Debounce delay in ms |
minQueryLength | number | 2 | Min characters for suggestions |
maxSuggestions | number | 10 | Max suggestions to show |
onSearch | (query, results) => void | - | Search callback |
onQueryChange | (query) => void | - | Query change callback |
onSuggestionSelect | (suggestion) => void | - | Suggestion select callback |
searchOptions | SearchOptions | - | Additional search options |
className | string | - | CSS class name |
style | CSSProperties | - | Inline styles |
theme | SearchBarTheme | - | Component theme |
renderSuggestion | (suggestion, index) => ReactNode | - | Custom suggestion render |
renderLoading | () => ReactNode | - | Custom loading render |
Example
<SearchBar
placeholder="Search products..."
showSuggestions={true}
debounceMs={300}
minQueryLength={2}
maxSuggestions={8}
onSearch={(query, results) => {
console.log(`Found ${results.totalResults} results for "${query}"`);
}}
onSuggestionSelect={(suggestion) => {
console.log('Selected:', suggestion);
}}
searchOptions={{
facet_by: 'category,brand',
}}
renderSuggestion={(suggestion, index) => (
<div className="custom-suggestion">
<span>{suggestion}</span>
</div>
)}
/>
SearchResults
Displays search results with customizable rendering.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
results | SearchResponse | - | Search results (auto from context) |
loading | boolean | - | Loading state |
error | Error | - | Error state |
onResultClick | (result, index) => void | - | Result click callback |
renderResult | (result, index, isActive) => ReactNode | - | Custom result render |
renderEmpty | () => ReactNode | - | Empty state render |
renderLoading | () => ReactNode | - | Loading state render |
renderError | (error) => ReactNode | - | Error state render |
className | string | - | CSS class name |
style | CSSProperties | - | Inline styles |
theme | SearchResultsTheme | - | Component theme |
itemsPerPage | number | 20 | Items per page |
showPagination | boolean | false | Show pagination |
viewMode | 'list' | 'card' | 'grid' | 'list' | Display mode |
fieldMapping | FieldMapping | - | Field mapping |
extractResults | (response) => any[] | - | Custom result extraction |
enableKeyboardNavigation | boolean | true | Keyboard nav support |
autoFocus | boolean | false | Auto focus first result |
Example
<SearchResults
viewMode="grid"
itemsPerPage={24}
fieldMapping={{
title: 'document.name',
image: 'document.imageUrl',
price: 'document.price',
}}
onResultClick={(result, index) => {
navigate(`/product/${result.id}`);
}}
renderResult={(result, index) => (
<div className="product-card">
<img src={result.image} alt={result.title} />
<h3>{result.title}</h3>
<span className="price">${result.price}</span>
</div>
)}
renderEmpty={() => (
<div className="empty-state">
<p>No results found</p>
</div>
)}
renderLoading={() => (
<div className="skeleton-grid">
{[...Array(8)].map((_, i) => (
<div key={i} className="skeleton-card" />
))}
</div>
)}
/>
QuerySuggestions
Standalone component for displaying query suggestions.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
query | string | '' | Current query |
maxSuggestions | number | 10 | Max suggestions |
debounceMs | number | 300 | Debounce delay |
minQueryLength | number | 2 | Min query length |
onSuggestionClick | (suggestion) => void | - | Click callback |
renderSuggestion | (suggestion, index) => ReactNode | - | Custom render |
renderLoading | () => ReactNode | - | Loading render |
renderEmpty | () => ReactNode | - | Empty render |
showTitle | boolean | false | Show title |
title | string | 'Suggestions' | Title text |
className | string | - | CSS class |
style | CSSProperties | - | Inline styles |
theme | QuerySuggestionsTheme | - | Component theme |
Example
<QuerySuggestions
query={searchQuery}
maxSuggestions={5}
showTitle={true}
title="Popular searches"
onSuggestionClick={(suggestion) => {
setSearchQuery(suggestion);
performSearch(suggestion);
}}
/>
Facets
Display and manage facet filters.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
facets | Record<string, FacetData> | - | Facet data (auto from context) |
onRefinementAdd | (field, value) => void | - | Add refinement callback |
onRefinementRemove | (field, value) => void | - | Remove refinement callback |
showCount | boolean | true | Show value counts |
sortBy | 'count' | 'alpha' | 'count' | Sort order |
limit | number | 10 | Values per facet |
showMore | boolean | true | Show "show more" button |
showSearch | boolean | false | Show facet search |
className | string | - | CSS class |
Example
<Facets
showCount={true}
sortBy="count"
limit={10}
showMore={true}
showSearch={true}
onRefinementAdd={(field, value) => {
console.log(`Added filter: ${field}=${value}`);
}}
/>
CurrentRefinements
Display active refinements/filters.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
refinements | Refinement[] | - | Active refinements |
onRemove | (refinement) => void | - | Remove callback |
renderRefinement | (refinement) => ReactNode | - | Custom render |
className | string | - | CSS class |
Example
<CurrentRefinements
renderRefinement={(refinement) => (
<span className="refinement-tag">
{refinement.label}: {refinement.value}
<button onClick={() => removeRefinement(refinement)}>×</button>
</span>
)}
/>
ClearRefinements
Button to clear all active refinements.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
onClear | () => void | - | Clear callback |
label | string | 'Clear all' | Button label |
disabled | boolean | - | Disabled state |
className | string | - | CSS class |
Example
<ClearRefinements
label="Clear all filters"
onClear={() => {
console.log('Filters cleared');
}}
/>
Pagination
Page navigation component.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
currentPage | number | - | Current page (from context) |
totalPages | number | - | Total pages (from context) |
onPageChange | (page) => void | - | Page change callback |
showFirst | boolean | true | Show first page button |
showLast | boolean | true | Show last page button |
showPrevNext | boolean | true | Show prev/next buttons |
siblingCount | number | 1 | Pages to show around current |
className | string | - | CSS class |
Example
<Pagination
showFirst={true}
showLast={true}
siblingCount={2}
onPageChange={(page) => {
window.scrollTo({ top: 0, behavior: 'smooth' });
}}
/>
SortBy
Sort options dropdown.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | SortOption[] | Required | Sort options |
value | string | - | Current value |
onChange | (value) => void | - | Change callback |
label | string | 'Sort by' | Label text |
className | string | - | CSS class |
SortOption
interface SortOption {
label: string;
value: string;
}
Example
<SortBy
label="Sort by"
items={[
{ label: 'Relevance', value: 'relevance:desc' },
{ label: 'Price: Low to High', value: 'price:asc' },
{ label: 'Price: High to Low', value: 'price:desc' },
{ label: 'Newest First', value: 'created_at:desc' },
{ label: 'Best Selling', value: 'sales:desc' },
]}
onChange={(value) => {
console.log('Sort changed to:', value);
}}
/>
HitsPerPage
Results per page selector.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | number[] | [10, 20, 50] | Options |
value | number | - | Current value |
onChange | (value) => void | - | Change callback |
label | string | 'Show' | Label text |
className | string | - | CSS class |
Example
<HitsPerPage
items={[12, 24, 48, 96]}
label="Products per page"
/>
Stats
Search statistics display.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
totalResults | number | - | Total results (from context) |
processingTimeMs | number | - | Processing time |
renderStats | (stats) => ReactNode | - | Custom render |
className | string | - | CSS class |
Example
<Stats
renderStats={({ totalResults, processingTimeMs }) => (
<span>
{totalResults.toLocaleString()} results
({processingTimeMs}ms)
</span>
)}
/>
RangeSlider
Numeric range filter slider.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
attribute | string | Required | Field name |
min | number | - | Minimum value |
max | number | - | Maximum value |
step | number | 1 | Step increment |
onChange | (range) => void | - | Change callback |
formatValue | (value) => string | - | Value formatter |
className | string | - | CSS class |
Example
<RangeSlider
attribute="price"
min={0}
max={1000}
step={10}
formatValue={(value) => `$${value}`}
onChange={({ min, max }) => {
addFilter('price', `${min}-${max}`);
}}
/>
Highlight
Highlight matching text in results.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
hit | object | Required | Result object |
attribute | string | Required | Field to highlight |
tagName | string | 'mark' | Highlight tag |
className | string | - | CSS class |
Example
<Highlight
hit={result}
attribute="title"
tagName="mark"
/>
InfiniteHits
Infinite scroll results display.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
threshold | number | 200 | Load threshold in px |
renderResult | (result, index) => ReactNode | - | Result render |
renderLoading | () => ReactNode | - | Loading render |
renderEnd | () => ReactNode | - | End of results render |
className | string | - | CSS class |
Example
<InfiniteHits
threshold={300}
renderResult={(result) => (
<ProductCard product={result} />
)}
renderLoading={() => (
<div className="loading-spinner" />
)}
renderEnd={() => (
<p>You've reached the end!</p>
)}
/>
Field Mapping
Configure how component fields map to your data:
interface FieldMapping {
title?: string; // e.g., 'document.productName'
description?: string; // e.g., 'document.brandDesc'
image?: string; // e.g., 'document.image'
price?: string; // e.g., 'document.mrp'
url?: string; // e.g., 'document.url'
id?: string; // e.g., 'id'
primaryText?: string; // Widget view field
secondaryText?: string; // Widget view field
tertiaryText?: string; // Widget view field
imageUrl?: string; // Widget view field
custom?: Record<string, string>; // Custom fields
}
Example with Nested Fields
<SearchProvider
client={client}
fieldMapping={{
title: 'document.product.name',
description: 'document.product.description',
image: 'document.images[0].url',
price: 'document.pricing.current',
id: 'id',
}}
>
<SearchResults />
</SearchProvider>
Next Steps
- React Hooks - Hooks reference
- Premium Suggestions - Rich autocomplete
- Theming - Customize appearance