Vue Components
The Seekora UI SDK provides Vue 3 components that mirror the React component API.
Installation
npm install @seekora-ai/ui-sdk-vue @seekora-ai/search-sdk
Setup
Basic Setup
<template>
<SearchProvider :client="client">
<SearchBar placeholder="Search products..." />
<SearchResults />
</SearchProvider>
</template>
<script setup>
import { SeekoraClient } from '@seekora-ai/search-sdk';
import { SearchProvider, SearchBar, SearchResults } from '@seekora-ai/ui-sdk-vue';
const client = new SeekoraClient({
storeId: 'your-store-id',
readSecret: 'your-read-secret',
});
</script>
With Plugin
// main.ts
import { createApp } from 'vue';
import { SeekoraPlugin } from '@seekora-ai/ui-sdk-vue';
import App from './App.vue';
const app = createApp(App);
app.use(SeekoraPlugin, {
storeId: 'your-store-id',
readSecret: 'your-read-secret',
});
app.mount('#app');
<!-- App.vue -->
<template>
<SearchProvider>
<SearchBar />
<SearchResults />
</SearchProvider>
</template>
<script setup>
import { SearchProvider, SearchBar, SearchResults } from '@seekora-ai/ui-sdk-vue';
</script>
Components
SearchProvider
<template>
<SearchProvider
:client="client"
:theme="customTheme"
:enable-analytics="true"
>
<slot />
</SearchProvider>
</template>
<script setup>
import { SearchProvider } from '@seekora-ai/ui-sdk-vue';
const props = defineProps({
client: { type: Object, required: true },
theme: { type: Object, default: null },
enableAnalytics: { type: Boolean, default: true },
});
</script>
SearchBar
<template>
<SearchBar
placeholder="Search products..."
:show-suggestions="true"
:debounce-ms="300"
:max-suggestions="10"
@search="handleSearch"
@query-change="handleQueryChange"
@suggestion-select="handleSuggestionSelect"
/>
</template>
<script setup>
import { SearchBar } from '@seekora-ai/ui-sdk-vue';
const handleSearch = (query, results) => {
console.log(`Found ${results.totalResults} results for "${query}"`);
};
const handleQueryChange = (query) => {
console.log('Query:', query);
};
const handleSuggestionSelect = (suggestion) => {
console.log('Selected:', suggestion);
};
</script>
SearchResults
<template>
<SearchResults
view-mode="grid"
:items-per-page="24"
@result-click="handleResultClick"
>
<template #result="{ result, index }">
<div class="product-card">
<img :src="result.image" :alt="result.title" />
<h3>{{ result.title }}</h3>
<span class="price">${{ result.price }}</span>
</div>
</template>
<template #empty>
<div class="empty-state">
<p>No results found</p>
</div>
</template>
<template #loading>
<div class="loading">Loading...</div>
</template>
</SearchResults>
</template>
<script setup>
import { SearchResults } from '@seekora-ai/ui-sdk-vue';
const handleResultClick = (result, index) => {
router.push(`/product/${result.id}`);
};
</script>
QuerySuggestions
<template>
<QuerySuggestions
:query="searchQuery"
:max-suggestions="5"
:show-title="true"
title="Suggestions"
@suggestion-click="handleSuggestionClick"
>
<template #suggestion="{ suggestion, index }">
<div class="suggestion-item">
<SearchIcon />
<span>{{ suggestion }}</span>
</div>
</template>
</QuerySuggestions>
</template>
<script setup>
import { ref } from 'vue';
import { QuerySuggestions } from '@seekora-ai/ui-sdk-vue';
const searchQuery = ref('');
const handleSuggestionClick = (suggestion) => {
searchQuery.value = suggestion;
};
</script>
Facets
<template>
<Facets
:show-count="true"
sort-by="count"
:limit="10"
:show-more="true"
@refinement-add="handleRefinementAdd"
@refinement-remove="handleRefinementRemove"
/>
</template>
<script setup>
import { Facets } from '@seekora-ai/ui-sdk-vue';
const handleRefinementAdd = (field, value) => {
console.log(`Added: ${field}=${value}`);
};
const handleRefinementRemove = (field, value) => {
console.log(`Removed: ${field}=${value}`);
};
</script>
Pagination
<template>
<Pagination
:show-first="true"
:show-last="true"
:sibling-count="2"
@page-change="handlePageChange"
/>
</template>
<script setup>
import { Pagination } from '@seekora-ai/ui-sdk-vue';
const handlePageChange = (page) => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};
</script>
SortBy
<template>
<SortBy
label="Sort by"
:items="sortOptions"
@change="handleSortChange"
/>
</template>
<script setup>
import { SortBy } from '@seekora-ai/ui-sdk-vue';
const sortOptions = [
{ label: 'Relevance', value: 'relevance:desc' },
{ label: 'Price: Low to High', value: 'price:asc' },
{ label: 'Price: High to Low', value: 'price:desc' },
];
const handleSortChange = (value) => {
console.log('Sort:', value);
};
</script>
Composables
useSeekoraSearch
<script setup>
import { ref } from 'vue';
import { useSeekoraSearch } from '@seekora-ai/ui-sdk-vue';
const { search, results, loading, error, clearResults } = useSeekoraSearch({
client,
autoTrack: true,
});
const query = ref('');
const handleSearch = async () => {
await search(query.value, {
per_page: 20,
facet_by: 'category,brand',
});
};
</script>
<template>
<div>
<input v-model="query" @keyup.enter="handleSearch" />
<button @click="handleSearch" :disabled="loading">
{{ loading ? 'Searching...' : 'Search' }}
</button>
<div v-if="error">{{ error.message }}</div>
<div v-if="results">
<div v-for="result in results.results" :key="result.id">
{{ result.title }}
</div>
</div>
</div>
</template>
useQuerySuggestions
<script setup>
import { ref, watch } from 'vue';
import { useQuerySuggestions } from '@seekora-ai/ui-sdk-vue';
const query = ref('');
const { suggestions, loading, error } = useQuerySuggestions({
client,
query,
debounceMs: 300,
maxSuggestions: 8,
});
</script>
<template>
<div>
<input v-model="query" />
<ul v-if="suggestions.length > 0">
<li v-for="(suggestion, index) in suggestions" :key="index">
{{ suggestion }}
</li>
</ul>
</div>
</template>
useSearchState
<script setup>
import { useSearchState } from '@seekora-ai/ui-sdk-vue';
const {
query,
setQuery,
results,
currentPage,
setPage,
refinements,
addRefinement,
removeRefinement,
clearRefinements,
sortBy,
setSortBy,
} = useSearchState();
</script>
<template>
<div>
<input :value="query" @input="setQuery($event.target.value)" />
<div v-for="ref in refinements" :key="`${ref.field}-${ref.value}`">
{{ ref.field }}: {{ ref.value }}
<button @click="removeRefinement(ref.field, ref.value)">×</button>
</div>
<button v-if="refinements.length" @click="clearRefinements">
Clear all
</button>
<div v-if="results">
Found {{ results.totalResults }} results
</div>
</div>
</template>
useSearchContext
<script setup>
import { useSearchContext } from '@seekora-ai/ui-sdk-vue';
const { client, theme, analytics } = useSearchContext();
</script>
Complete Example
<template>
<SearchProvider :client="client" :theme="theme">
<div class="search-page">
<header>
<SearchBar
placeholder="Search products..."
:show-suggestions="true"
@search="handleSearch"
/>
</header>
<div class="search-layout">
<aside class="sidebar">
<ClearRefinements />
<Facets :show-count="true" />
</aside>
<main class="content">
<div class="toolbar">
<Stats />
<CurrentRefinements />
<SortBy :items="sortOptions" />
</div>
<SearchResults view-mode="grid">
<template #result="{ result }">
<ProductCard :product="result" />
</template>
</SearchResults>
<Pagination />
</main>
</div>
</div>
</SearchProvider>
</template>
<script setup>
import { SeekoraClient } from '@seekora-ai/search-sdk';
import {
SearchProvider,
SearchBar,
SearchResults,
Facets,
CurrentRefinements,
ClearRefinements,
Pagination,
SortBy,
Stats,
} from '@seekora-ai/ui-sdk-vue';
import ProductCard from './ProductCard.vue';
const client = new SeekoraClient({
storeId: 'your-store-id',
readSecret: 'your-read-secret',
});
const theme = {
colors: {
primary: '#6366f1',
},
};
const sortOptions = [
{ label: 'Relevance', value: 'relevance:desc' },
{ label: 'Price: Low to High', value: 'price:asc' },
{ label: 'Price: High to Low', value: 'price:desc' },
];
const handleSearch = (query, results) => {
console.log(`Found ${results.totalResults} results`);
};
</script>
<style scoped>
.search-page {
max-width: 1200px;
margin: 0 auto;
}
.search-layout {
display: grid;
grid-template-columns: 250px 1fr;
gap: 24px;
margin-top: 24px;
}
.toolbar {
display: flex;
justify-content: space-between;
margin-bottom: 16px;
}
</style>
TypeScript Support
<script setup lang="ts">
import { ref } from 'vue';
import { SeekoraClient, SearchResponse } from '@seekora-ai/search-sdk';
import { SearchProvider, SearchBar, SearchResults } from '@seekora-ai/ui-sdk-vue';
import type { SearchBarProps, Theme } from '@seekora-ai/ui-sdk-vue';
const client = new SeekoraClient({
storeId: 'your-store-id',
readSecret: 'your-read-secret',
});
const theme: Partial<Theme> = {
colors: {
primary: '#6366f1',
},
};
const handleSearch = (query: string, results: SearchResponse) => {
console.log(`Found ${results.totalResults} results`);
};
</script>
Next Steps
- React Components - React component reference
- Angular Components - Angular component reference
- Vanilla JS - Vanilla JavaScript reference