Search
Search input with suggestion dropdown, grouped results, matched-text highlight, recent searches, async loading state, ⌘K command palette mode, and expandable animation.
Import
import Search from '$lib/components/Search.svelte';
import type { SearchItem } from '$lib/components/Search.svelte';Usage
<script lang="ts">
let value = $state('');
</script>
<Search bind:value placeholder="Search..." />Sizes
Three size presets: sm, md (default), lg.
<Search size="sm" placeholder="Small..." />
<Search size="md" placeholder="Medium..." />
<Search size="lg" placeholder="Large..." />Expandable
Set expandable to collapse the input to a search icon; it expands with a spring animation on click and closes on blur.
<!-- Collapses to an icon; expands on click with a spring animation -->
<Search expandable size="sm" placeholder="Search..." recentKey="exp-sm" />Suggestions, grouped results & highlight
Pass items to show a suggestion dropdown. Results are grouped by category, matched text is highlighted, badges are shown. Recent searches are persisted via recentKey. Try: "svelte", "frontend", "#svelte"
<script lang="ts">
let q = $state('');
const items: SearchItem[] = [
{ id: 1, label: 'Svelte 5 Runes', description: '12:34 · 284K views', category: 'Videos', badge: 'Trending' },
{ id: 2, label: 'CSS Grid', description: '24:10 · 112K views', category: 'Videos' },
];
const results = $derived(q.trim()
? items.filter(i => i.label.toLowerCase().includes(q.toLowerCase()))
: []);
</script>
<Search
bind:value={q}
placeholder="Search videos..."
items={results}
recentKey="search-demo"
onSelect={(item) => console.log(item)}
/>Async search
Simulated API call with 800ms delay — shows a spinner and loading dots. Pass loading=true while your request is in flight.
<script lang="ts">
let q = $state('');
let loading = $state(false);
let results = $state<SearchItem[]>([]);
let timer: ReturnType<typeof setTimeout>;
function onSearch(query: string) {
clearTimeout(timer);
if (!query) { results = []; return; }
loading = true;
timer = setTimeout(async () => {
results = await fetchResults(query);
loading = false;
}, 400);
}
</script>
<Search bind:value={q} {items} {loading} onSearch={onSearch} recentKey="async" />Command palette (⌘K)
Set command to register a global keyboard shortcut. Focus with ⌘K or Ctrl+K. Try: "button", "slider", "dashboard"
<Search
bind:value={q}
placeholder="Search components or pages..."
items={results}
command
shortcut="⌘K"
size="lg"
recentKey="cmdk"
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | '' | Bindable input value. |
placeholder | string | 'Search...' | Input placeholder text. |
size | 'sm' | 'md' | 'lg' | 'md' | Controls height and font size. |
items | SearchItem[] | — | Suggestion items to display in the dropdown. |
loading | boolean | false | Shows a spinner and loading dots in the dropdown. |
debounce | number | — | Milliseconds to debounce the onSearch callback. |
maxRecent | number | — | Max recent searches to store. |
recentKey | string | — | localStorage key for persisting recent searches. Unique per instance. |
command | boolean | false | Enables ⌘K / Ctrl+K global keyboard shortcut to focus the input. |
shortcut | string | — | Shortcut badge label shown inside the input (e.g. "⌘K"). |
emptyText | string | — | Text shown when items is empty and a query is active. |
expandable | boolean | false | Collapses to an icon; expands on click with a spring animation. |
onSearch | (q: string) => void | — | Callback fired on every input change (after optional debounce). |