Styling Guide & Demo Stores
This guide shows how to style Search UI components and Query Suggestions with CSS so you can match your site’s look or build multiple demo stores (e-commerce, minimal, dark, etc.) using the same components.
How styling works
You can style components in three ways:
| Method | Use when |
|---|---|
| 1. CSS variables | One stylesheet drives colors, fonts, spacing for all components. Best for brand-wide or theme switching. |
| 2. Theme / classNames props | You pass class names per component (or per slot). Components render those classes; you style them in your CSS. |
| 3. className & style | You add a root class or inline style to a component. Good for one-off overrides or wrapper-based styling. |
For demo stores, combine 1 (variables per store) with 2 (wire components to the core CSS classes or your own classes).
Setup
1. Import the core stylesheet
The SDK ships a CSS file that defines variables and optional BEM classes. Import it once (e.g. in your app entry or layout):
// App.tsx or layout
import '@seekora-ai/ui-sdk-core/styles/seekora.css';
Or via CDN:
<link rel="stylesheet" href="https://unpkg.com/@seekora-ai/ui-sdk-core/styles/seekora.css" />
2. Wrap your app with SearchProvider
Pass a theme (or rely on defaults). Theme drives inline styles (e.g. colors, spacing) when you don’t pass custom theme (class names) to individual components.
import { SearchProvider, defaultTheme } from '@seekora-ai/ui-sdk-react';
<SearchProvider client={client} theme={defaultTheme}>
<YourSearchUI />
</SearchProvider>
3. Optionally enable core CSS classes on components
By default, React components use the theme from context for inline styles and only use class names if you pass a theme (or classNames) prop. To style with the built-in BEM classes from seekora.css, pass the class names below in each component’s theme (or classNames) prop. Then your CSS (or the same seekora.css) will apply.
CSS variables reference
Override these in :root or on a wrapper (e.g. [data-demo-store="fashion"]) to restyle everything that uses them.
Colors
--seekora-color-primary
--seekora-color-secondary
--seekora-color-background
--seekora-color-surface
--seekora-color-text
--seekora-color-textSecondary
--seekora-color-border
--seekora-color-hover
--seekora-color-focus
--seekora-color-error
--seekora-color-success
--seekora-color-warning
Typography
--seekora-font-family
--seekora-font-size-small /* e.g. 0.875rem */
--seekora-font-size-medium /* e.g. 1rem */
--seekora-font-size-large /* e.g. 1.25rem */
--seekora-font-weight-normal
--seekora-font-weight-medium
--seekora-font-weight-semibold
--seekora-font-weight-bold
--seekora-line-height-tight
--seekora-line-height-normal
--seekora-line-height-relaxed
Spacing & layout
--seekora-spacing-small /* e.g. 0.5rem */
--seekora-spacing-medium /* e.g. 1rem */
--seekora-spacing-large /* e.g. 1.5rem */
Border radius
--seekora-border-radius
--seekora-border-radius-none
--seekora-border-radius-small
--seekora-border-radius-medium
--seekora-border-radius-large
--seekora-border-radius-full
Shadows & motion
--seekora-shadow-small
--seekora-shadow-medium
--seekora-shadow-large
--seekora-transition-fast
--seekora-transition-normal
--seekora-transition-slow
Z-index
--seekora-z-index-dropdown
--seekora-z-index-modal
--seekora-z-index-tooltip
Built-in theme switches
You can switch the whole look by setting a data attribute (the stylesheet already defines these):
<html data-seekora-theme="light"> <!-- default -->
<html data-seekora-theme="dark">
<html data-seekora-theme="minimal">
<html data-seekora-theme="high-contrast">
Search UI components
For each component you can:
- Pass theme with class names that match the core BEM classes below (so
seekora.cssapplies), or your own classes. - Pass className and style on the root for overrides.
SearchBar
Props: className, style, theme?: SearchBarTheme
Theme slots (class names):
| Slot | Purpose | Core BEM class (optional) |
|---|---|---|
| container | Wrapper | seekora-search-bar |
| input | Input field | seekora-search-bar__input |
| inputFocused | Input when focused | seekora-search-bar--focused (on container) |
| suggestionsContainer | Suggestions dropdown | (custom) |
| suggestionItem | One suggestion | (custom) |
| suggestionItemActive | Selected suggestion | (custom) |
| loadingIndicator | Loading UI | (custom) |
Example – use core CSS + your overrides:
<SearchBar
className="my-store-search-bar"
theme={{
container: 'seekora-search-bar',
input: 'seekora-search-bar__input',
suggestionsContainer: 'seekora-search-bar-suggestions',
suggestionItem: 'seekora-search-bar-suggestion',
suggestionItemActive: 'seekora-search-bar-suggestion--active',
}}
/>
/* Your CSS: override variables for this block only */
.my-store-search-bar {
--seekora-color-primary: #c41e3a;
--seekora-border-radius-medium: 24px;
}
.my-store-search-bar.seekora-search-bar {
border-radius: 24px;
border-width: 2px;
}
SearchResults
Props: className, style, theme?: SearchResultsTheme
Theme slots:
| Slot | Purpose | Core BEM class |
|---|---|---|
| container | Root | seekora-results |
| header | Header row | (custom) |
| resultsList | List | seekora-results__list |
| resultItem | One result row | seekora-results__item |
| resultItemHover | Hover/active state | seekora-results__item--active |
| resultTitle | Title | seekora-results__title |
| resultDescription | Description | seekora-results__description |
| resultImage | Image | seekora-results__image |
| resultPrice | Price | seekora-results__price |
| emptyState | No results | seekora-results__empty |
| loadingState | Loading | seekora-results__loading |
| errorState | Error | seekora-results__error |
Example:
<SearchResults
className="my-store-results"
theme={{
container: 'seekora-results',
resultsList: 'seekora-results__list',
resultItem: 'seekora-results__item',
resultItemHover: 'seekora-results__item--active',
resultTitle: 'seekora-results__title',
resultDescription: 'seekora-results__description',
resultImage: 'seekora-results__image',
resultPrice: 'seekora-results__price',
emptyState: 'seekora-results__empty',
loadingState: 'seekora-results__loading',
errorState: 'seekora-results__error',
}}
/>
.my-store-results .seekora-results__item {
border-radius: 8px;
margin-bottom: 8px;
}
.my-store-results .seekora-results__price {
color: var(--seekora-color-primary);
font-size: 1.125rem;
}
Pagination
Props: className, style, theme?: PaginationTheme
Theme slots:
| Slot | Core BEM class |
|---|---|
| container | seekora-pagination |
| list | (wrapper for items) |
| item | seekora-pagination__item |
| itemActive | seekora-pagination__item--active |
| itemDisabled | seekora-pagination__item--disabled |
| link | (inside item) |
| ellipsis | seekora-pagination__ellipsis |
Example:
<Pagination
theme={{
container: 'seekora-pagination',
list: 'seekora-pagination__list',
item: 'seekora-pagination__item',
itemActive: 'seekora-pagination__item--active',
itemDisabled: 'seekora-pagination__item--disabled',
ellipsis: 'seekora-pagination__ellipsis',
}}
/>
Facets
Props: className, style, theme?: FacetsTheme
Theme slots:
| Slot | Core BEM class |
|---|---|
| container | (root) |
| facet | seekora-facets__facet |
| facetTitle | seekora-facets__title |
| facetList | seekora-facets__list |
| facetItem | seekora-facets__item |
| checkbox | seekora-facets__checkbox |
| facetItemLabel | seekora-facets__label |
| facetItemCount | seekora-facets__count |
Core container class: seekora-facets.
Example:
<Facets
className="my-store-facets"
theme={{
container: 'seekora-facets',
facet: 'seekora-facets__facet',
facetTitle: 'seekora-facets__title',
facetList: 'seekora-facets__list',
facetItem: 'seekora-facets__item',
checkbox: 'seekora-facets__checkbox',
facetItemLabel: 'seekora-facets__label',
facetItemCount: 'seekora-facets__count',
}}
/>
Stats
Props: className, style, theme?: StatsTheme
Theme slots: container, text, highlight, separator.
Core: seekora-stats, seekora-stats__count, seekora-stats__query, seekora-stats__time.
<Stats
theme={{
container: 'seekora-stats',
text: 'seekora-stats__count',
separator: 'seekora-stats__time',
}}
/>
SortBy
Props: className, style, theme?: SortByTheme
Theme slots: container, select, option.
Core: seekora-sort-by, seekora-sort-by__label, seekora-sort-by__select.
<SortBy
options={sortOptions}
theme={{
container: 'seekora-sort-by',
select: 'seekora-sort-by__select',
option: 'seekora-sort-by__option',
}}
/>
CurrentRefinements
Props: className, style, theme?: CurrentRefinementsTheme
Theme slots: container, list, item, label, value, clearButton, clearAllButton.
Core: seekora-refinements, seekora-refinements__item, seekora-refinements__clear, seekora-refinements__clear-all.
<CurrentRefinements
theme={{
container: 'seekora-refinements',
item: 'seekora-refinements__item',
clearButton: 'seekora-refinements__clear',
clearAllButton: 'seekora-refinements__clear-all',
}}
/>
ClearRefinements
Props: className, style, theme?: ClearRefinementsTheme
Theme slots: root, button, buttonDisabled.
Core: seekora-clear-refinements, seekora-clear-refinements__button, seekora-clear-refinements__button--disabled.
<ClearRefinements
theme={{
root: 'seekora-clear-refinements',
button: 'seekora-clear-refinements__button',
buttonDisabled: 'seekora-clear-refinements__button--disabled',
}}
/>
RangeInput
Theme slots: container, label, inputGroup, input, separator, button.
Core: seekora-range-input, seekora-range-input__label, seekora-range-input__input, seekora-range-input__button, etc.
RangeSlider
Theme slots: root, label, slider, track, trackFilled, thumb, values, value.
HitsPerPage
Theme slots: root, select, option.
Core: seekora-hits-per-page, seekora-hits-per-page__select.
InfiniteHits
Theme slots: root, list, item, loadMore, loadMoreDisabled, loading, empty, sentinel.
Core: seekora-infinite-hits, seekora-infinite-hits__show-more.
Breadcrumb
Theme slots: root, list, item, link, separator, current.
HierarchicalMenu
Theme slots: root, list, item, itemSelected, itemParent, link, label, count, showMore.
Highlight / Snippet
Theme slots (Highlight): root, highlighted, nonHighlighted.
Snippet: same + ellipsis.
Core for highlight: seekora-highlight, seekora-highlight__highlighted, seekora-snippet, seekora-snippet__highlighted.
SearchLayout
Theme slots: container, sidebar, main, header, footer.
Core: seekora-layout, seekora-layout__sidebar, seekora-layout__main, seekora-layout__header, seekora-layout__footer.
MobileFilters
Theme slots: overlay, drawer, header, title, closeButton, content, footer, applyButton, clearButton, filterCount.
Recommendations
Theme slots: root, title, list, item, image, content, name, price, loading, empty.
Query suggestions components
These components support classNames (and often className / style) so you can target every part with CSS.
SearchBarWithSuggestions
Combines an input with a suggestions dropdown. You can pass classNames (and className / style) to the underlying dropdown; the wrapper also accepts classNames.wrapper (e.g. seekora-search-bar-with-suggestions).
Example:
import { SearchBarWithSuggestions } from '@seekora-ai/ui-sdk-react';
<SearchBarWithSuggestions
variant="minimal" // or "google" | "amazon" | "shopify" | "pinterest" | "spotlight" | "federated" | "mobile-sheet"
placeholder="Search products..."
className="my-store-search-bar-with-suggestions"
classNames={{
root: 'my-store-suggestions-root',
container: 'my-store-suggestions-container',
section: 'my-store-suggestions-section',
sectionTitle: 'my-store-suggestions-section-title',
suggestionsList: 'my-store-suggestions-list',
suggestionItem: 'my-store-suggestion-item',
suggestionItemActive: 'my-store-suggestion-item--active',
recentSearches: 'my-store-recent-searches',
recentItem: 'my-store-recent-item',
productsList: 'my-store-products-list',
productItem: 'my-store-product-item',
productImage: 'my-store-product-image',
productTitle: 'my-store-product-title',
productPrice: 'my-store-product-price',
tabsList: 'my-store-tabs-list',
tabItem: 'my-store-tab-item',
tabActive: 'my-store-tab-item--active',
brandsList: 'my-store-brands-list',
brandItem: 'my-store-brand-item',
trendingSearches: 'my-store-trending',
trendingItem: 'my-store-trending-item',
}}
/>
Then in your CSS:
.my-store-search-bar-with-suggestions .my-store-suggestion-item {
padding: 12px 16px;
border-radius: 8px;
}
.my-store-search-bar-with-suggestions .my-store-suggestion-item--active {
background: var(--seekora-color-hover);
}
.my-store-search-bar-with-suggestions .my-store-product-item {
border: 1px solid var(--seekora-color-border);
border-radius: 8px;
}
QuerySuggestionsDropdown
Props: classNames?: QuerySuggestionsClassNames, className, style.
Same classNames shape as above: root, container, section, sectionTitle, suggestionsList, suggestionItem, suggestionItemActive, recentSearches, recentItem, productsList, productItem, productImage, productTitle, productPrice, tabsList, tabItem, tabActive, brandsList, brandItem, trendingSearches, trendingItem, etc.
RichQuerySuggestions
Props: classNames?: QuerySuggestionsClassNames, style.
Use the same QuerySuggestionsClassNames keys. Root/container get merged with seekora-rich-suggestions and your classNames.root / classNames.container.
FederatedDropdown
Props: classNames?: QuerySuggestionsClassNames, style.
Same classNames as above. Root uses seekora-federated-dropdown plus your classNames.
QuerySuggestions (standalone list)
Props: className, style, theme?: QuerySuggestionsTheme (container, title, suggestionsList, suggestionItem, suggestionItemHover, suggestionItemActive, loadingState, emptyState).
Use theme to pass class names for the list and items so you can style them with CSS.
Demo store themes (CSS-only)
You can define one CSS file per “store” and switch by body class or data attribute.
Store 1: Minimal / editorial
[data-demo-store="minimal"] {
--seekora-color-primary: #000;
--seekora-color-text: #1a1a1a;
--seekora-color-textSecondary: #666;
--seekora-color-border: #e0e0e0;
--seekora-font-family: Georgia, "Times New Roman", serif;
--seekora-font-size-medium: 15px;
--seekora-font-size-large: 18px;
--seekora-border-radius-none: 0;
--seekora-border-radius-small: 0;
--seekora-border-radius-medium: 0;
--seekora-shadow-small: none;
--seekora-shadow-medium: none;
--seekora-shadow-large: none;
}
<html data-demo-store="minimal">
<SearchProvider client={client} theme={minimalTheme}>
<SearchBar theme={{ container: 'seekora-search-bar', input: 'seekora-search-bar__input' }} />
<SearchResults theme={{ container: 'seekora-results', resultItem: 'seekora-results__item', /* ... */ }} />
</SearchProvider>
</html>
Store 2: E-commerce (warm)
[data-demo-store="ecommerce"] {
--seekora-color-primary: #f59e0b;
--seekora-color-secondary: #10b981;
--seekora-color-background: #ffffff;
--seekora-color-surface: #fafafa;
--seekora-color-text: #1f2937;
--seekora-color-textSecondary: #6b7280;
--seekora-color-border: #e5e7eb;
--seekora-font-family: "Inter", sans-serif;
--seekora-border-radius-medium: 8px;
--seekora-border-radius-large: 16px;
--seekora-shadow-medium: 0 4px 6px rgba(0, 0, 0, 0.07);
}
Store 3: Dark / tech
[data-demo-store="dark"] {
--seekora-color-primary: #6366f1;
--seekora-color-background: #0f172a;
--seekora-color-surface: #1e293b;
--seekora-color-text: #f1f5f9;
--seekora-color-textSecondary: #94a3b8;
--seekora-color-border: #334155;
--seekora-color-hover: #334155;
--seekora-font-family: "JetBrains Mono", "Fira Code", monospace;
--seekora-border-radius-medium: 10px;
--seekora-shadow-small: 0 0 10px rgba(99, 102, 241, 0.1);
--seekora-shadow-medium: 0 0 20px rgba(99, 102, 241, 0.15);
}
Store 4: Fashion / luxury (custom brand)
[data-demo-store="fashion"] {
--seekora-color-primary: #c41e3a;
--seekora-color-secondary: #8b7355;
--seekora-color-background: #faf9f7;
--seekora-color-surface: #ffffff;
--seekora-color-text: #2c2c2c;
--seekora-color-textSecondary: #6b6b6b;
--seekora-font-family: "Cormorant Garamond", "Times New Roman", serif;
--seekora-font-size-medium: 15px;
--seekora-font-size-large: 20px;
--seekora-border-radius-medium: 0;
--seekora-border-radius-large: 0;
--seekora-shadow-small: 0 1px 3px rgba(0,0,0,0.06);
}
Switch store in JS:
const [store, setStore] = useState('ecommerce');
useEffect(() => {
document.documentElement.setAttribute('data-demo-store', store);
}, [store]);
Quick reference
| Component | Root className/style | Theme / classNames |
|---|---|---|
| SearchBar | ✅ className, style | theme: SearchBarTheme (container, input, suggestionsContainer, suggestionItem, …) |
| SearchResults | ✅ className, style | theme: SearchResultsTheme (container, resultsList, resultItem, resultTitle, …) |
| Pagination | ✅ className, style | theme: PaginationTheme (container, list, item, itemActive, ellipsis) |
| Facets | ✅ className, style | theme: FacetsTheme (container, facet, facetTitle, facetList, facetItem, …) |
| Stats | ✅ className, style | theme: StatsTheme (container, text, highlight, separator) |
| SortBy | ✅ className, style | theme: SortByTheme (container, select, option) |
| CurrentRefinements | ✅ className, style | theme: CurrentRefinementsTheme (container, item, clearButton, clearAllButton) |
| ClearRefinements | ✅ className, style | theme: ClearRefinementsTheme (root, button, buttonDisabled) |
| RangeInput | ✅ className, style | theme: RangeInputTheme |
| RangeSlider | ✅ className, style | theme: RangeSliderTheme |
| HitsPerPage | ✅ className, style | theme: HitsPerPageTheme |
| InfiniteHits | ✅ className, style | theme: InfiniteHitsTheme |
| Breadcrumb | ✅ className, style | theme: BreadcrumbTheme |
| HierarchicalMenu | ✅ className, style | theme: HierarchicalMenuTheme |
| Highlight / Snippet | ✅ className, style | theme: HighlightTheme / SnippetTheme |
| SearchLayout | ✅ className, style | theme: SearchLayoutTheme (container, sidebar, main, header, footer) |
| MobileFilters | ✅ className, style | theme: MobileFiltersTheme |
| Recommendations | ✅ className, style | theme: RecommendationTheme |
| QuerySuggestions | ✅ className, style | theme: QuerySuggestionsTheme |
| SearchBarWithSuggestions | ✅ className, style, classNames | classNames: QuerySuggestionsClassNames (root, container, section, suggestionItem, productItem, …) |
| QuerySuggestionsDropdown | ✅ className, style | classNames: QuerySuggestionsClassNames |
| RichQuerySuggestions | ✅ style | classNames: QuerySuggestionsClassNames |
| FederatedDropdown | ✅ style | classNames: QuerySuggestionsClassNames |
Checklist for a new demo store
- Import
@seekora-ai/ui-sdk-core/styles/seekora.css. - Define a store selector (e.g.
data-demo-store="store-id") and override--seekora-*variables in CSS for that selector. - For each Search UI component you use, pass theme with either the core BEM class names from this guide or your own classes, and style those classes in your CSS.
- For SearchBarWithSuggestions (or any query suggestions dropdown), pass classNames with your own class names (or a mix with core), then style those in CSS.
- Optionally add className on the root of components for wrapper-level overrides (e.g.
.my-store-results .seekora-results__item { ... }).
With this, every component can be styled to match each website or demo store using CSS only, plus minimal props (theme/classNames) to attach your classes.