Section
Command Palette — Neo-Brutalism
Brutalist Cmd+K command palette overlay with hard black borders, offset drop shadows, and flat bright accents. Live search filters grouped commands, arrow keys move the highlight, Enter runs the selected command with a confirmation toast, Escape closes, and Cmd/Ctrl+K toggles open. Focus is trapped inside the palette and restored to the trigger on close.
- Section
- Tailwind
- HTML
- MIT
Preview
Live section
9:41 100%
devsnips.dev/library/tailwind/sections/developer/command-palette/neo-brutalism/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Sections/Developer/command-palette/neo-brutalism Tailwind/Sections/Developer/command-palette/neo-brutalism <!--
Snippet Name: Command Palette — Neo-Brutalism
Description: Brutalist Cmd+K command palette overlay with live search, grouped commands, arrow-key navigation, Enter to run, and Escape to close.
Author: DevSnips Contributors
Usage Example: Drop into any app shell. Click the trigger (or press Cmd/Ctrl+K) to open the palette.
-->
<div class="relative" data-cmd="nb">
<!-- Trigger -->
<button type="button" data-cmd-open
class="flex items-center gap-3 border-2 border-black bg-white px-4 py-3 font-archivo text-sm font-extrabold uppercase tracking-tight shadow-[4px_4px_0_0_#000] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-[1px_1px_0_0_#000] focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2">
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" aria-hidden="true"><path d="M12 3v18M3 12h18" /></svg>
Open command palette
<span class="ml-2 border-2 border-black bg-[#FFE600] px-1.5 py-0.5 font-mono text-[10px] font-bold uppercase">⌘K</span>
</button>
<!-- Overlay -->
<div data-cmd-overlay class="fixed inset-0 z-50 hidden items-start justify-center bg-black/40 px-4 pt-[12vh]" role="dialog" aria-modal="true" aria-labelledby="nb-cmd-title">
<div class="w-full max-w-xl border-2 border-black bg-white shadow-[8px_8px_0_0_#000]" data-cmd-panel>
<!-- Search -->
<div class="flex items-center gap-3 border-b-2 border-black bg-[#FFE600] px-4 py-3">
<svg class="h-5 w-5 shrink-0" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" aria-hidden="true"><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>
<label id="nb-cmd-title" class="sr-only">Command palette</label>
<input
type="text"
data-cmd-input
placeholder="Type a command or search…"
aria-label="Search commands"
aria-autocomplete="list"
aria-controls="nb-cmd-list"
class="w-full bg-transparent font-archivo text-[15px] font-bold placeholder:text-black/40 focus:outline-none"
/>
<button type="button" data-cmd-close aria-label="Close command palette"
class="flex h-8 w-8 shrink-0 items-center justify-center border-2 border-black bg-white shadow-[2px_2px_0_0_#000] transition-transform duration-100 hover:translate-x-[2px] hover:translate-y-[2px] hover:shadow-none focus:outline-none focus-visible:ring-2 focus-visible:ring-black focus-visible:ring-offset-2">
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" /></svg>
</button>
</div>
<!-- List -->
<div class="cmd-scroll max-h-[52vh] overflow-y-auto bg-[#FFFDF5] py-2" data-cmd-list-wrap>
<ul id="nb-cmd-list" role="listbox" aria-label="Commands" data-cmd-list></ul>
<p data-cmd-empty class="hidden px-4 py-8 text-center font-mono text-[11px] font-bold uppercase tracking-wider text-black/50">No matching commands</p>
</div>
<!-- Footer -->
<div class="flex flex-wrap items-center justify-between gap-2 border-t-2 border-black bg-white px-4 py-2.5">
<div class="flex items-center gap-3 font-mono text-[10px] font-bold uppercase tracking-wider text-black/60">
<span class="flex items-center gap-1"><span class="border-2 border-black bg-[#FFFDF5] px-1 py-0.5">↑</span><span class="border-2 border-black bg-[#FFFDF5] px-1 py-0.5">↓</span> navigate</span>
<span class="flex items-center gap-1"><span class="border-2 border-black bg-[#FFFDF5] px-1.5 py-0.5">↵</span> run</span>
<span class="flex items-center gap-1"><span class="border-2 border-black bg-[#FFFDF5] px-1.5 py-0.5">esc</span> close</span>
</div>
<span class="font-mono text-[10px] font-bold uppercase tracking-wider text-black/50">DevSnips</span>
</div>
</div>
</div>
<!-- Confirmation toast -->
<div data-cmd-toast class="pointer-events-none fixed bottom-6 left-1/2 z-[60] hidden -translate-x-1/2 border-2 border-black bg-[#00E676] px-4 py-2.5 font-mono text-[12px] font-bold uppercase tracking-wider shadow-[4px_4px_0_0_#000]" role="status" aria-live="polite"></div>
<style>
[data-cmd="nb"] .cmd-scroll::-webkit-scrollbar { width: 10px; }
[data-cmd="nb"] .cmd-scroll::-webkit-scrollbar-track { background: #FFFDF5; border-left: 2px solid #000; }
[data-cmd="nb"] .cmd-scroll::-webkit-scrollbar-thumb { background: #000; border: 2px solid #FFFDF5; }
[data-cmd="nb"] .cmd-scroll { scrollbar-width: thin; scrollbar-color: #000 #FFFDF5; }
</style>
<script>
(function () {
var root = document.currentScript.closest('[data-cmd="nb"]');
if (!root) return;
var openBtn = root.querySelector('[data-cmd-open]');
var overlay = root.querySelector('[data-cmd-overlay]');
var panel = root.querySelector('[data-cmd-panel]');
var input = root.querySelector('[data-cmd-input]');
var list = root.querySelector('[data-cmd-list]');
var empty = root.querySelector('[data-cmd-empty]');
var closeBtn = root.querySelector('[data-cmd-close]');
var toast = root.querySelector('[data-cmd-toast]');
var lastFocus = null;
var commands = [
{ group: 'Navigation', items: [
{ id: 'home', label: 'Go to Home', hint: 'Dashboard', kw: 'home dashboard', icon: 'M3 11l9-8 9 8M5 10v10h14V10' },
{ id: 'docs', label: 'Open Documentation', hint: 'Docs', kw: 'docs help guide', icon: 'M4 4h16v16H4zM8 8h8M8 12h8M8 16h5' },
{ id: 'snippets', label: 'Browse Snippets', hint: 'Library', kw: 'snippets library components', icon: 'M4 6h16M4 12h16M4 18h16' }
] },
{ group: 'Actions', items: [
{ id: 'new', label: 'New Snippet', hint: 'Create', kw: 'new create add', icon: 'M12 5v14M5 12h14' },
{ id: 'copy', label: 'Copy Current Snippet', hint: 'Duplicate', kw: 'copy duplicate clone', icon: 'M8 8h12v12H8M4 4h12v4M4 12v8h8' },
{ id: 'deploy', label: 'Deploy to Preview', hint: 'Ship', kw: 'deploy ship publish preview', icon: 'M5 12l5 5L20 7' }
] },
{ group: 'Settings', items: [
{ id: 'theme', label: 'Toggle Theme', hint: 'Appearance', kw: 'theme dark light appearance', icon: 'M12 3a9 9 0 100 18 7 7 0 010-18z' },
{ id: 'keys', label: 'Edit Keyboard Shortcuts', hint: 'Hotkeys', kw: 'keys keyboard shortcuts hotkeys', icon: 'M3 7h18M3 12h18M3 17h18' },
{ id: 'signout', label: 'Sign Out', hint: 'Account', kw: 'sign out logout account', icon: 'M16 17l5-5-5-5M21 12H9M9 21H4V3h5' }
] }
];
var flat = [];
commands.forEach(function (g) { g.items.forEach(function (it) { flat.push(it); }); });
var filtered = [];
var active = -1;
function render(q) {
q = (q || '').toLowerCase().trim();
filtered = [];
var html = '';
var shown = 0;
commands.forEach(function (g) {
var items = g.items.filter(function (it) {
return !q || it.label.toLowerCase().indexOf(q) > -1 || it.kw.indexOf(q) > -1 || it.hint.toLowerCase().indexOf(q) > -1;
});
if (!items.length) return;
html += '<li role="presentation" class="px-4 pt-2 pb-1 font-mono text-[10px] font-bold uppercase tracking-wider text-black/50">' + g.group + '</li>';
items.forEach(function (it) {
var idx = filtered.length;
filtered.push(it);
html +=
'<li role="option" data-idx="' + idx + '" aria-selected="false" tabindex="-1"' +
' class="cmd-item group flex cursor-pointer items-center gap-3 border-l-4 border-transparent px-4 py-2.5 transition-colors hover:bg-[#FFE600] aria-selected:bg-[#FFE600] aria-selected:border-black">' +
'<span class="flex h-9 w-9 shrink-0 items-center justify-center border-2 border-black bg-white shadow-[2px_2px_0_0_#000] group-hover:shadow-none"><svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="' + it.icon + '"/></svg></span>' +
'<span class="min-w-0 flex-1"><span class="block font-archivo text-[14px] font-bold leading-tight">' + it.label + '</span><span class="block font-mono text-[10px] font-bold uppercase tracking-wider text-black/50">' + it.hint + '</span></span>' +
'<span class="border-2 border-black bg-[#00C2FF] px-1.5 py-0.5 font-mono text-[10px] font-bold uppercase">run</span>' +
'</li>';
});
});
list.innerHTML = html;
empty.classList.toggle('hidden', filtered.length > 0);
active = filtered.length ? 0 : -1;
setActive();
bindItems();
}
function setActive() {
var items = list.querySelectorAll('.cmd-item');
items.forEach(function (el, i) {
var sel = (i === active);
el.setAttribute('aria-selected', sel ? 'true' : 'false');
});
var el = items[active];
if (el) {
input.setAttribute('aria-activedescendant', el.getAttribute('data-idx'));
el.scrollIntoView({ block: 'nearest' });
} else {
input.removeAttribute('aria-activedescendant');
}
}
function move(step) {
if (!filtered.length) return;
active = (active + step + filtered.length) % filtered.length;
setActive();
}
function runCommand(it) {
showToast('Ran: ' + it.label);
}
function showToast(msg) {
toast.textContent = msg;
toast.classList.remove('hidden');
clearTimeout(showToast._t);
showToast._t = setTimeout(function () { toast.classList.add('hidden'); }, 1800);
}
function bindItems() {
list.querySelectorAll('.cmd-item').forEach(function (el, i) {
el.addEventListener('mouseenter', function () { active = i; setActive(); });
el.addEventListener('click', function () { if (filtered[i]) runCommand(filtered[i]); close(); });
});
}
function open() {
if (!overlay.classList.contains('hidden')) return;
lastFocus = document.activeElement;
overlay.classList.remove('hidden');
overlay.classList.add('flex');
input.value = '';
render('');
requestAnimationFrame(function () { input.focus(); });
}
function close() {
overlay.classList.add('hidden');
overlay.classList.remove('flex');
input.removeAttribute('aria-activedescendant');
if (lastFocus && typeof lastFocus.focus === 'function') lastFocus.focus();
}
function trap(e) {
if (e.key === 'Escape') { e.preventDefault(); close(); return; }
if (e.key === 'ArrowDown') { e.preventDefault(); move(1); return; }
if (e.key === 'ArrowUp') { e.preventDefault(); move(-1); return; }
if (e.key === 'Enter') {
e.preventDefault();
if (filtered[active]) { var it = filtered[active]; close(); runCommand(it); }
return;
}
if (e.key === 'Tab') {
e.preventDefault();
move(e.shiftKey ? -1 : 1);
}
}
openBtn.addEventListener('click', open);
closeBtn.addEventListener('click', close);
overlay.addEventListener('mousedown', function (e) { if (e.target === overlay) close(); });
input.addEventListener('input', function () { render(input.value); });
overlay.addEventListener('keydown', trap);
document.addEventListener('keydown', function (e) {
if ((e.metaKey || e.ctrlKey) && (e.key === 'k' || e.key === 'K')) {
e.preventDefault();
if (overlay.classList.contains('hidden')) open(); else close();
}
});
render('');
})();
</script>
</div> 222 lines UTF-8 · LF · Spaces: 2
Continue browsing