Your server's results
Commands and search results in one list — debounced, aborted and cached, with the highlight staying where it was.
<div class="demo">
<button class="demo-btn" id="open">Open the palette</button>
<p class="demo-hint">Type two letters: local commands stay, invoices arrive under their own heading.</p>
<div class="demo-kv">
<div><span class="demo-hint">keystrokes</span><br><b id="typed">0</b></div>
<div><span class="demo-hint">requests sent</span><br><b id="calls">0</b></div>
</div>
</div>
import { createCommandPalette } from 'https://www.devix.pk/cdn/oss/command-palette@1.0.0/index.js';
const INVOICES = Array.from({ length: 60 }, (_, i) => ({ id: 1000 + i, customer: ['Aisha Khan', 'Bilal Ahmed', 'Chen Wei', 'Dana Ali'][i % 4], total: (i + 1) * 120 }));
const count = (id) => (document.getElementById(id).textContent = String(Number(document.getElementById(id).textContent) + 1));
const palette = createCommandPalette({
recents: false,
minChars: 2,
debounce: 200,
items: [
{ id: 'go.invoices', title: 'Go to invoices', section: 'Go to', perform: () => {} },
{ id: 'go.customers', title: 'Go to customers', section: 'Go to', perform: () => {} },
{ id: 'invoice.new', title: 'New invoice', section: 'Create', perform: () => {} },
],
onSelect: () => count('typed') && undefined,
// Stands in for your API: 350ms of latency, and it can be cancelled.
search: (query, { signal }) => {
count('calls');
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
const found = INVOICES.filter((invoice) => `${invoice.id} ${invoice.customer}`.toLowerCase().includes(query.toLowerCase()));
resolve(found.slice(0, 8).map((invoice) => ({
id: `inv-${invoice.id}`,
title: `Invoice #${invoice.id}`,
subtitle: invoice.customer,
meta: `AED ${invoice.total.toLocaleString()}`,
section: 'Invoices',
perform: () => {},
})));
}, 350);
signal.addEventListener('abort', () => {
clearTimeout(timer);
reject(new DOMException('cancelled', 'AbortError'));
});
});
},
});
// Count keystrokes for the comparison with requests sent.
document.addEventListener('keydown', (event) => {
if (palette.isOpen && event.key.length === 1) count('typed');
});
document.getElementById('open').addEventListener('click', () => palette.open());
@import url('https://www.devix.pk/cdn/oss/command-palette@1.0.0/command-palette.min.css');