CommandPalette
commandpalette-1779354232008.tsx
'use client';
import { useState, useEffect } from 'react';
interface Command {
id: number;
title: string;
description: string;
}
const commands: Command[] = [
{ id: 1, title: 'New File', description: 'Create a new file' },
{ id: 2, title: 'Open File', description: 'Open an existing file' },
{ id: 3, title: 'Save File', description: 'Save the current file' },
{ id: 4, title: 'Close File', description: 'Close the current file' },
];
const CommandPalette = () => {
const [isOpen, setIsOpen] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
const [filteredCommands, setFilteredCommands] = useState(commands);
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.metaKey && event.key === 'k') {
setIsOpen(true);
}
};
document.addEventListener('keydown', handleKeyDown);
return () => {
document.removeEventListener('keydown', handleKeyDown);
};
}, []);
useEffect(() => {
const filtered = commands.filter((command) =>
command.title.toLowerCase().includes(searchQuery.toLowerCase())
);
setFilteredCommands(filtered);
}, [searchQuery]);
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSearchQuery(event.target.value);
setSelectedCommandIndex(0);
};
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'ArrowDown') {
setSelectedCommandIndex(
(selectedCommandIndex + 1) % filteredCommands.length
);
} else if (event.key === 'ArrowUp') {
setSelectedCommandIndex(
(selectedCommandIndex - 1 + filteredCommands.length) %
filteredCommands.length
);
} else if (event.key === 'Enter') {
// Handle command execution
console.log(`Executing command: ${filteredCommands[selectedCommandIndex].title}`);
setIsOpen(false);
}
};
return (
<div
className={`fixed top-0 left-0 w-full h-full bg-zinc-950 transition-all duration-300 ${
isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'
}`}
>
<div
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-1/2 max-w-sm bg-zinc-900 rounded-lg shadow-lg p-4"
style={{ boxShadow: '0px 0px 10px 5px rgba(0, 0, 0, 0.5)' }}
>
<input
type="search"
placeholder="Search commands..."
className="w-full p-2 pl-10 text-sm text-zinc-200 bg-zinc-800 rounded-lg focus:outline-none focus:ring-2 focus:ring-c9a84c"
value={searchQuery}
onChange={handleSearchChange}
onKeyDown={handleKeyDown}
autoFocus
/>
<ul>
{filteredCommands.map((command, index) => (
<li
key={command.id}
className={`py-2 px-4 text-sm text-zinc-200 cursor-pointer ${
index === selectedCommandIndex
? 'bg-zinc-800'
: 'hover:bg-zinc-700'
}`}
>
<span className="text-c9a84c">{command.title}</span>
<span className="text-zinc-500 ml-2">{command.description}</span>
</li>
))}
</ul>
</div>
</div>
);
};
export default CommandPalette;Component info
CategoryOverlays
Frameworkreact
TierFREE
Views0
Copies0
About
Cmd+K command palette search modal
More from Overlays
import React, { useState } from 'react';
import './SlideDrawer.css';
interface SlideDrawerProps {
isOpen: boolean;
onClose: () => void;
children: React.ReactNode;
}
const SlideDrawer: React.FC<SlideDrawerProps> = ({ isOpen, onClose, children SlideDrawer
Overlays
import React, { useState } from 'react';
interface ContextMenuProps {
children: React.ReactNode;
}
const ContextMenu: React.FC<ContextMenuProps> = ({ children }) => {
const [showMenu, setShowMenu] = useState(false);
const [x, setX] = useStateContextMenu
Overlays
'use client';
import React, { useState } from 'react';
interface AlertDialogProps {
isOpen: boolean;
onClose: () => void;
onConfirm: () => void;
title: string;
description: string;
}
const AlertDialog: React.FC<AlertDialogProps> = ({
iAlertDialog
Overlays
'use client';
import React, { useState } from 'react';
interface TooltipProps {
children: React.ReactNode;
content: string;
direction?: 'top' | 'bottom' | 'left' | 'right';
}
const Tooltip: React.FC<TooltipProps> = ({ children, content, direTooltip
Overlays