Component
Command Menu
IDE-style command palette with keyboard shortcuts, search filtering, grouped commands, and keyboard navigation hints.
- Component
- Tailwind
- HTML
- MIT
Preview
Live component
9:41 100%
devsnips.dev/library/tailwind/components/dropdowns/command-menu/ fluid · no fixed width 100%
Install
Add to your project
npx devsnips add Tailwind/Components/Dropdowns/command-menu Tailwind/Components/Dropdowns/command-menu <!-- Command Menu (IDE-style) -->
<div class="relative">
<div
id="command-trigger"
class="flex items-center gap-3 w-full max-w-lg px-4 py-3 bg-gray-100 border border-gray-200 rounded-xl cursor-pointer hover:bg-gray-200 transition-colors"
onclick="openCommandMenu()"
>
<svg class="w-5 h-5 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<span class="flex-1 text-sm text-gray-500">Search commands, settings, or actions...</span>
<kbd class="hidden sm:inline-flex items-center gap-1 px-2 py-1 text-xs text-gray-400 bg-white border border-gray-200 rounded">
<span>⌘</span><span>K</span>
</kbd>
</div>
<!-- Command Palette -->
<div
id="command-menu"
class="hidden fixed inset-0 z-50 bg-black/50 flex items-start justify-center pt-24"
onclick="closeCommandMenu(event)"
>
<div
class="w-full max-w-xl bg-white rounded-2xl shadow-2xl border border-gray-200 overflow-hidden"
onclick="event.stopPropagation()"
>
<!-- Search Input -->
<div class="p-4 border-b border-gray-100">
<div class="relative">
<svg class="absolute left-4 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
</svg>
<input
type="text"
id="command-search"
class="w-full pl-12 pr-4 py-3 text-lg bg-gray-50 border-0 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Type a command or search..."
oninput="filterCommands(this.value)"
autofocus
/>
</div>
</div>
<!-- Command Categories -->
<div class="max-h-96 overflow-y-auto">
<!-- Navigation -->
<div class="px-4 py-2">
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Navigation</p>
</div>
<div class="px-2 pb-2">
<button class="command-item w-full flex items-center gap-3 px-3 py-2.5 text-sm text-gray-700 rounded-lg hover:bg-blue-50 transition-colors" onclick="executeCommand('dashboard')">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
</svg>
<span>Go to Dashboard</span>
<span class="ml-auto text-xs text-gray-400">⌘D</span>
</button>
<button class="command-item w-full flex items-center gap-3 px-3 py-2.5 text-sm text-gray-700 rounded-lg hover:bg-blue-50 transition-colors" onclick="executeCommand('projects')">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"></path>
</svg>
<span>Go to Projects</span>
<span class="ml-auto text-xs text-gray-400">⌘P</span>
</button>
<button class="command-item w-full flex items-center gap-3 px-3 py-2.5 text-sm text-gray-700 rounded-lg hover:bg-blue-50 transition-colors" onclick="executeCommand('settings')">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
</svg>
<span>Open Settings</span>
<span class="ml-auto text-xs text-gray-400">⌘,</span>
</button>
</div>
<!-- Actions -->
<div class="px-4 py-2 border-t border-gray-100">
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Actions</p>
</div>
<div class="px-2 pb-2">
<button class="command-item w-full flex items-center gap-3 px-3 py-2.5 text-sm text-gray-700 rounded-lg hover:bg-blue-50 transition-colors" onclick="executeCommand('new-file')">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
</svg>
<span>Create New File</span>
<span class="ml-auto text-xs text-gray-400">⌘N</span>
</button>
<button class="command-item w-full flex items-center gap-3 px-3 py-2.5 text-sm text-gray-700 rounded-lg hover:bg-blue-50 transition-colors" onclick="executeCommand('share')">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"></path>
</svg>
<span>Share Project</span>
<span class="ml-auto text-xs text-gray-400">⌘⇧S</span>
</button>
<button class="command-item w-full flex items-center gap-3 px-3 py-2.5 text-sm text-gray-700 rounded-lg hover:bg-blue-50 transition-colors" onclick="executeCommand('export')">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"></path>
</svg>
<span>Export as PNG</span>
<span class="ml-auto text-xs text-gray-400">⌘E</span>
</button>
</div>
<!-- Theme -->
<div class="px-4 py-2 border-t border-gray-100">
<p class="text-xs font-semibold text-gray-400 uppercase tracking-wider">Theme</p>
</div>
<div class="px-2 pb-4">
<button class="command-item w-full flex items-center gap-3 px-3 py-2.5 text-sm text-gray-700 rounded-lg hover:bg-blue-50 transition-colors" onclick="executeCommand('theme')">
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
</svg>
<span>Toggle Dark Mode</span>
<span class="ml-auto text-xs text-gray-400">⌘⇧D</span>
</button>
</div>
</div>
<!-- Footer -->
<div class="px-4 py-3 bg-gray-50 border-t border-gray-100 flex items-center justify-between text-xs text-gray-500">
<div class="flex items-center gap-4">
<span class="flex items-center gap-1"><kbd class="px-1.5 py-0.5 bg-white border border-gray-200 rounded">↑↓</kbd> Navigate</span>
<span class="flex items-center gap-1"><kbd class="px-1.5 py-0.5 bg-white border border-gray-200 rounded">↵</kbd> Select</span>
</div>
<span class="flex items-center gap-1"><kbd class="px-1.5 py-0.5 bg-white border border-gray-200 rounded">Esc</kbd> Close</span>
</div>
</div>
</div>
</div>
<script>
function openCommandMenu() {
document.getElementById('command-menu').classList.remove('hidden');
document.getElementById('command-search').focus();
}
function closeCommandMenu(event) {
if (event.target.id === 'command-menu') {
document.getElementById('command-menu').classList.add('hidden');
}
}
function filterCommands(query) {
const normalizedQuery = query.toLowerCase();
document.querySelectorAll('.command-item').forEach(item => {
const text = item.textContent.toLowerCase();
if (text.includes(normalizedQuery)) {
item.classList.remove('hidden');
} else {
item.classList.add('hidden');
}
});
}
function executeCommand(command) {
console.log('Executing command:', command);
document.getElementById('command-menu').classList.add('hidden');
}
document.addEventListener('keydown', function(event) {
if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
event.preventDefault();
openCommandMenu();
}
if (event.key === 'Escape') {
document.getElementById('command-menu').classList.add('hidden');
}
});
</script> # Command Menu
Command palette style menu.
## Preview
Open `preview.html` for a standalone demonstration.
## Features
- Searchable command list
- Keyboard-oriented layout
## Usage
```bash
npx devsnips add Tailwind/Components/Dropdowns/command-menu
```
Copy from `code.html`.
## Customization
- Input and list styles, widths
## Accessibility
- Strong keyboard support is expected for command menus
## Dependencies
- Tailwind CSS; JS for filtering/open state as present in markup
## File Structure
- `code.html` · `preview.html` · `metadata.json` · `README.md` 168 lines UTF-8 · LF · Spaces: 2
Continue browsing