Bootstrap Command Palette — Free HTML CSS JS Snippet
Bootstrap Command Palette · Navigation · Plain HTML, CSS & JS · Live preview
Copy & paste
Source Code
<div class="container py-5 d-flex justify-content-center">
<div class="card bscmd-card">
<div class="card-body p-4 text-center">
<p class="small text-muted mb-2">Press Ctrl+K (or Cmd+K on Mac), or click below.</p>
<button type="button" class="btn btn-outline-secondary" id="bscmdOpen">
Search commands <kbd class="ms-1">Ctrl</kbd><kbd>K</kbd>
</button>
<p class="small mt-3 mb-0" id="bscmdStatus"> </p>
</div>
</div>
</div>
<div class="modal fade" id="bscmdModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content bscmd-modal-content">
<div class="p-2 border-bottom">
<input type="text" class="form-control border-0 bscmd-input" id="bscmdInput" placeholder="Type a command...">
</div>
<ul class="list-unstyled mb-0 bscmd-list" id="bscmdList"></ul>
</div>
</div>
</div>.bscmd-card { width: 380px; max-width: 100%; border: 1px solid #eceef1; border-radius: 14px; }
.bscmd-modal-content { border-radius: 14px; overflow: hidden; }
.bscmd-input:focus { box-shadow: none; }
.bscmd-list { max-height: 280px; overflow-y: auto; padding: 6px; }
.bscmd-item { display: flex; justify-content: space-between; padding: 9px 10px; border-radius: 8px; font-size: 13.5px; cursor: pointer; }
.bscmd-item-active { background: #eef0ff; color: #4338ca; }
.bscmd-item span.bscmd-hint { color: #9ca3af; font-size: 11.5px; }const COMMANDS = [
{ label: 'Go to Dashboard', hint: 'Navigation' },
{ label: 'Create new project', hint: 'Action' },
{ label: 'Invite teammate', hint: 'Action' },
{ label: 'Open settings', hint: 'Navigation' },
{ label: 'Toggle dark mode', hint: 'Preference' },
{ label: 'View billing', hint: 'Navigation' },
{ label: 'Log out', hint: 'Account' },
];
const openBtn = document.getElementById('bscmdOpen');
const input = document.getElementById('bscmdInput');
const list = document.getElementById('bscmdList');
const status = document.getElementById('bscmdStatus');
const modalEl = document.getElementById('bscmdModal');
const modal = new bootstrap.Modal(modalEl);
let activeIndex = 0;
let visible = COMMANDS;
function render() {
const q = input.value.trim().toLowerCase();
visible = q ? COMMANDS.filter(c => c.label.toLowerCase().includes(q)) : COMMANDS;
activeIndex = Math.min(activeIndex, Math.max(visible.length - 1, 0));
list.innerHTML = visible.map((c, i) =>
'<li class="bscmd-item' + (i === activeIndex ? ' bscmd-item-active' : '') + '" data-index="' + i + '">' +
'<span>' + c.label + '</span><span class="bscmd-hint">' + c.hint + '</span></li>'
).join('') || '<li class="bscmd-item text-muted">No matching commands</li>';
}
function runCommand(cmd) {
status.textContent = 'Ran: "' + cmd.label + '"';
modal.hide();
}
function open() {
input.value = '';
activeIndex = 0;
render();
modal.show();
}
openBtn.addEventListener('click', open);
document.addEventListener('keydown', e => {
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') {
e.preventDefault();
open();
}
});
modalEl.addEventListener('shown.bs.modal', () => input.focus());
input.addEventListener('input', render);
input.addEventListener('keydown', e => {
if (e.key === 'ArrowDown') {
e.preventDefault();
activeIndex = Math.min(activeIndex + 1, visible.length - 1);
render();
} else if (e.key === 'ArrowUp') {
e.preventDefault();
activeIndex = Math.max(activeIndex - 1, 0);
render();
} else if (e.key === 'Enter' && visible[activeIndex]) {
runCommand(visible[activeIndex]);
}
});
list.addEventListener('click', e => {
const item = e.target.closest('.bscmd-item');
if (item && visible[Number(item.dataset.index)]) runCommand(visible[Number(item.dataset.index)]);
});
render();Extend with AI
Take This Snippet Further With AI
The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.
What's included
Features
About this UI Snippet
Bootstrap Command Palette — HTML, CSS & JavaScript

Filtering and keyboard navigation share one activeIndex and one visible array, both recomputed together inside render() — every keystroke re-filters COMMANDS into visible, then clamps activeIndex with Math.min(activeIndex, visible.length - 1) so a highlighted row can never point past the end of a list that just got shorter mid-search. Skipping that clamp is the single most common bug in a homemade command palette: filter down to two results while the fourth item was highlighted, and the highlight silently vanishes or throws trying to read an item that no longer exists.
The palette opens through two different triggers — clicking the button, or a global keydown listener checking (e.ctrlKey || e.metaKey) && e.key === 'k' — and both funnel through the same open() function, which resets the query and activeIndex before showing the modal, so a stale search from a previous session never lingers into the next one. Bootstrap's own shown.bs.modal event is what focuses the input, deliberately after the modal's own opening transition completes rather than immediately on open, since focusing an element still mid-transition can be unreliable across browsers.
Step by step
How to Use
- 1Press Ctrl+K (or Cmd+K on Mac)The palette opens as a real Bootstrap modal with the input already focused.
- 2Type part of a command, like "dash"The list filters live to just "Go to Dashboard".
- 3Press the down arrow a few timesThe highlighted row moves down the filtered list and never overshoots the last item.
- 4Press EnterThe highlighted command runs, the palette closes, and a status message confirms which one.
- 5Reopen and click a command directly insteadClicking any row runs it exactly the same way pressing Enter on it would.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
Resetting to 0 on every keystroke would keep yanking the highlight back to the top while a user is trying to arrow down toward a specific item — clamping only intervenes when the current index has actually become invalid, preserving the user's position otherwise.
Ctrl+K is free in most browsers on most platforms (Firefox uses it for the search bar in older versions, which is the one real exception), which is why command palettes conventionally offer Cmd+K as the equivalent on Mac — e.preventDefault() stops the default browser behavior once the modal opens.
Yes. Track query and activeIndex in component state, derive the filtered visible list in the render function, and attach the global keydown listener in a mount lifecycle hook (useEffect, onMounted) with cleanup on unmount.
Replace the status message inside runCommand() with a real router push, a function call, or a dispatched action — everything else (filtering, keyboard nav, modal lifecycle) is unrelated to what a command actually does when it runs.
Yes. While the Bootstrap Command Palette snippet gives you one pattern to copy, the free Responsive Navbar Builder at webdevpuneet.com/navbar-builder/ designs a whole navigation bar: logo, links and dropdown menus, a mobile hamburger menu (dropdown panel, slide-in drawer or full screen) and a scroll effect (sticky, shrink, hide on scroll or transparent). It has six presets, a live preview that runs the real code, and exports HTML + CSS + vanilla JS, React, Tailwind, Vue 3 or Angular — or you can click Fork & Edit to keep editing it in My Code.