Section
Command Palette — Sharp Glassmorphism
Frosted-glass Cmd+K command palette floating over an animated gradient mesh, with luminous edges, blurred surfaces, and a fuchsia-to-indigo active highlight. 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. The glass needs a colored backdrop behind the panel to read.
- Section
- Tailwind
- HTML
- MIT
Preview
Live section
9:41 100%
devsnips.dev/library/tailwind/sections/developer/command-palette/sharp-glassmorphism/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Sections/Developer/command-palette/sharp-glassmorphism Tailwind/Sections/Developer/command-palette/sharp-glassmorphism <!--
Snippet Name: Command Palette — Sharp Glassmorphism
Description: Frosted-glass Cmd+K command palette floating over an animated gradient mesh, with luminous edges, live search, grouped commands, and full keyboard navigation.
Author: DevSnips Contributors
Usage Example: Drop into a colored shell (parent must provide a colored backdrop). Click the trigger (or press Cmd/Ctrl+K) to open the palette.
-->
<div class="relative" data-cmd="sg">
<!-- Trigger -->
<button type="button" data-cmd-open
class="sg-mono inline-flex items-center gap-2.5 rounded-xl border border-white/20 bg-white/10 px-3.5 py-2.5 text-[13px] font-medium text-white backdrop-blur transition-colors hover:bg-white/20 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/60">
<svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>
Search commands
<span class="ml-1 rounded-lg border border-white/20 bg-white/15 px-1.5 py-0.5 text-[10px] text-white/80 backdrop-blur">⌘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-[14vh] backdrop-blur-sm" role="dialog" aria-modal="true" aria-labelledby="sg-cmd-title">
<div class="relative w-full max-w-xl" data-cmd-panel>
<div class="sg-glow relative overflow-hidden rounded-2xl border border-white/20 bg-white/10 backdrop-blur-2xl">
<div class="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-white/50 to-transparent" aria-hidden="true"></div>
<!-- Search -->
<div class="flex items-center gap-3 border-b border-white/15 px-4 py-3.5">
<svg class="h-4 w-4 shrink-0 text-white/70" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><circle cx="11" cy="11" r="7" /><path d="m20 20-3.5-3.5" /></svg>
<label id="sg-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="sg-cmd-list"
class="w-full bg-transparent font-sora text-[15px] font-medium text-white placeholder:text-white/40 focus:outline-none"
/>
<span class="sg-mono shrink-0 rounded-lg border border-white/20 bg-white/10 px-1.5 py-0.5 text-[10px] text-white/70 backdrop-blur">esc</span>
</div>
<!-- List -->
<div class="cmd-scroll max-h-[52vh] overflow-y-auto py-2" data-cmd-list-wrap>
<ul id="sg-cmd-list" role="listbox" aria-label="Commands" data-cmd-list></ul>
<p data-cmd-empty class="hidden px-4 py-10 text-center font-sora text-[13px] text-white/60">No matching commands</p>
</div>
<!-- Footer -->
<div class="flex flex-wrap items-center justify-between gap-2 border-t border-white/15 px-4 py-2.5">
<div class="flex items-center gap-3 sg-mono text-[11px] text-white/60">
<span class="flex items-center gap-1"><kbd class="rounded-lg border border-white/20 bg-white/10 px-1.5 py-0.5 backdrop-blur">↑</kbd><kbd class="rounded-lg border border-white/20 bg-white/10 px-1.5 py-0.5 backdrop-blur">↓</kbd> navigate</span>
<span class="flex items-center gap-1"><kbd class="rounded-lg border border-white/20 bg-white/10 px-1.5 py-0.5 backdrop-blur">↵</kbd> run</span>
<span class="flex items-center gap-1"><kbd class="rounded-lg border border-white/20 bg-white/10 px-1.5 py-0.5 backdrop-blur">esc</kbd> close</span>
</div>
<span class="sg-mono flex items-center text-[11px] text-white/70"><span class="sg-dot"></span> DevSnips</span>
</div>
</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 items-center gap-2 rounded-xl border border-white/20 bg-white/10 px-4 py-2.5 font-sora text-[13px] font-medium text-white backdrop-blur-2xl" role="status" aria-live="polite" style="box-shadow:0 0 0 1px rgba(255,255,255,0.08),0 8px 30px -6px rgba(168,85,247,0.5);"></div>
<style>
[data-cmd="sg"] .font-sora { font-family: 'Sora', sans-serif; }
[data-cmd="sg"] .sg-mono { font-family: 'JetBrains Mono', ui-monospace, monospace; }
[data-cmd="sg"] .sg-dot { display: inline-block; height: 6px; width: 6px; border-radius: 9999px; background: #6ee7ff; margin-right: 6px; box-shadow: 0 0 8px #6ee7ff; vertical-align: middle; }
[data-cmd="sg"] .sg-glow { box-shadow: 0 0 0 1px rgba(255,255,255,0.08), 0 8px 40px -8px rgba(168,85,247,0.45); }
[data-cmd="sg"] .cmd-scroll::-webkit-scrollbar { width: 6px; }
[data-cmd="sg"] .cmd-scroll::-webkit-scrollbar-track { background: transparent; }
[data-cmd="sg"] .cmd-scroll::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 9999px; }
[data-cmd="sg"] .cmd-scroll { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,0.25) transparent; }
</style>
<script>
(function () {
var root = document.currentScript.closest('[data-cmd="sg"]');
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 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' },
{ id: 'settings', label: 'Open Settings', hint: 'Account', kw: 'settings account config', icon: 'M12 8a4 4 0 100 8 4 4 0 000-8zM19 12a7 7 0 11-14 0 7 7 0 0114 0z' }
] },
{ 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' },
{ id: 'share', label: 'Copy Share Link', hint: 'Share', kw: 'share link copy url', icon: 'M10 13a5 5 0 007 0l2-2a5 5 0 00-7-7l-1 1M14 11a5 5 0 00-7 0l-2 2a5 5 0 007 7l1-1' }
] },
{ 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 filtered = [];
var active = -1;
function render(q) {
q = (q || '').toLowerCase().trim();
filtered = [];
var html = '';
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="sg-mono px-4 pt-3 pb-1 text-[10px] uppercase tracking-wider text-white/55">' + 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 mx-2 flex cursor-pointer items-center gap-3 rounded-xl border border-transparent px-3 py-2.5 text-white/85 transition-colors hover:bg-white/15 hover:text-white aria-selected:bg-gradient-to-r aria-selected:from-fuchsia-500/30 aria-selected:to-indigo-500/30 aria-selected:border-white/25 aria-selected:text-white">' +
'<span class="sg-glow flex h-8 w-8 shrink-0 items-center justify-center rounded-lg border border-white/30 bg-white/20 text-white backdrop-blur group-hover:bg-white/30 aria-selected:bg-white/30"><svg class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="' + it.icon + '"/></svg></span>' +
'<span class="min-w-0 flex-1"><span class="block font-sora text-[14px] font-medium leading-tight">' + it.label + '</span></span>' +
'<span class="sg-mono shrink-0 text-[11px] text-white/50">' + it.hint + '</span>' +
'<span class="sg-mono hidden shrink-0 items-center gap-1 text-[10px] text-cyan-200 aria-selected:flex"><svg class="h-3 w-3" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M5 12l5 5L20 7"/></svg>enter</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.innerHTML = '<span class="sg-dot"></span>' + msg;
toast.classList.remove('hidden');
toast.classList.add('flex');
clearTimeout(showToast._t);
showToast._t = setTimeout(function () { toast.classList.add('hidden'); toast.classList.remove('flex'); }, 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]) { var it = filtered[i]; close(); runCommand(it); } });
});
}
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);
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> 225 lines UTF-8 · LF · Spaces: 2
Continue browsing