Implementação com Claude Code
Aprenda sobre implementação usando o Claude Code. Dicas práticas e exemplos de código incluídos.
Melhorando Drasticamente a Experiência do Usuário com Command Palette
O command palette, visto no VSCode e Slack, é um elemento de UI voltado para power users que permite operações rápidas apenas com o teclado. Com o Claude Code, você pode implementar eficientemente um command palette com busca, filtragem e navegação por teclado.
Componente Básico de Command Palette
> Implemente um command palette que abre com Cmd+K (Mac) / Ctrl+K (Windows).
> Suporte a busca, operação por teclado e exibição por categoria.
// components/CommandPalette.tsx
import { useState, useEffect, useRef, useCallback } from 'react';
interface Command {
id: string;
label: string;
category: string;
icon?: string;
shortcut?: string;
action: () => void;
}
interface CommandPaletteProps {
commands: Command[];
}
export function CommandPalette({ commands }: CommandPaletteProps) {
const [isOpen, setIsOpen] = useState(false);
const [query, setQuery] = useState('');
const [selectedIndex, setSelectedIndex] = useState(0);
const inputRef = useRef<HTMLInputElement>(null);
const filtered = commands.filter(cmd =>
cmd.label.toLowerCase().includes(query.toLowerCase()) ||
cmd.category.toLowerCase().includes(query.toLowerCase())
);
// Atalho global
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
setIsOpen(prev => !prev);
}
if (e.key === 'Escape') setIsOpen(false);
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, []);
// Controle de foco
useEffect(() => {
if (isOpen) {
inputRef.current?.focus();
setQuery('');
setSelectedIndex(0);
}
}, [isOpen]);
const handleKeyNav = useCallback((e: React.KeyboardEvent) => {
switch (e.key) {
case 'ArrowDown':
e.preventDefault();
setSelectedIndex(i => Math.min(i + 1, filtered.length - 1));
break;
case 'ArrowUp':
e.preventDefault();
setSelectedIndex(i => Math.max(i - 1, 0));
break;
case 'Enter':
e.preventDefault();
if (filtered[selectedIndex]) {
filtered[selectedIndex].action();
setIsOpen(false);
}
break;
}
}, [filtered, selectedIndex]);
if (!isOpen) return null;
return (
<div className="fixed inset-0 z-50 flex items-start justify-center pt-[20vh]">
<div className="fixed inset-0 bg-black/50" onClick={() => setIsOpen(false)} />
<div className="relative w-full max-w-lg rounded-xl bg-white shadow-2xl dark:bg-gray-800">
<input
ref={inputRef}
type="text"
value={query}
onChange={e => { setQuery(e.target.value); setSelectedIndex(0); }}
onKeyDown={handleKeyNav}
placeholder="Buscar comando..."
className="w-full border-b px-4 py-3 text-lg outline-none dark:bg-gray-800"
/>
<ul className="max-h-80 overflow-y-auto p-2" role="listbox">
{filtered.map((cmd, index) => (
<li
key={cmd.id}
role="option"
aria-selected={index === selectedIndex}
onClick={() => { cmd.action(); setIsOpen(false); }}
className={`flex cursor-pointer items-center justify-between rounded-lg px-3 py-2
${index === selectedIndex ? 'bg-blue-50 dark:bg-blue-900/30' : 'hover:bg-gray-50'}`}
>
<div className="flex items-center gap-3">
{cmd.icon && <span className="text-lg">{cmd.icon}</span>}
<div>
<div className="font-medium">{cmd.label}</div>
<div className="text-xs text-gray-500">{cmd.category}</div>
</div>
</div>
{cmd.shortcut && (
<kbd className="rounded bg-gray-100 px-2 py-1 text-xs dark:bg-gray-700">
{cmd.shortcut}
</kbd>
)}
</li>
))}
{filtered.length === 0 && (
<li className="px-3 py-8 text-center text-gray-500">
Nenhum comando encontrado
</li>
)}
</ul>
</div>
</div>
);
}
Definição e Registro de Comandos
// hooks/useCommands.ts
import { useRouter } from 'next/navigation';
export function useCommands(): Command[] {
const router = useRouter();
return [
{
id: 'home', label: 'Ir para Home', category: 'Navegação',
icon: '🏠', shortcut: 'G H',
action: () => router.push('/'),
},
{
id: 'blog', label: 'Lista do Blog', category: 'Navegação',
icon: '📝', shortcut: 'G B',
action: () => router.push('/blog'),
},
{
id: 'theme', label: 'Alternar Tema', category: 'Configurações',
icon: '🌙', shortcut: 'T T',
action: () => document.documentElement.classList.toggle('dark'),
},
{
id: 'search', label: 'Buscar Artigos', category: 'Busca',
icon: '🔍', shortcut: '/',
action: () => router.push('/search'),
},
];
}
Suporte a Acessibilidade
// Aplicação de WAI-ARIA
<div
role="dialog"
aria-modal="true"
aria-label="Command palette"
>
<input
role="combobox"
aria-expanded="true"
aria-controls="command-list"
aria-activedescendant={`command-${filtered[selectedIndex]?.id}`}
/>
<ul id="command-list" role="listbox">
{/* ... */}
</ul>
</div>
Resumo
O command palette, combinado com atalhos de teclado, melhora significativamente a produtividade de power users. Com o Claude Code, você pode implementar em pouco tempo um command palette completo com busca, filtragem e navegação por teclado. Considere também a acessibilidade para criar uma UI acessível a todos os usuários. Como referência de implementação, considere também a biblioteca cmdk.
Related Posts
Como Turbinar Seus Projetos Pessoais com o Claude Code [Com Exemplos]
Aprenda a acelerar drasticamente projetos de desenvolvimento pessoal usando o Claude Code. Inclui exemplos reais e um workflow prático da ideia ao deploy.
Como Automatizar Refatoração com o Claude Code
Aprenda a automatizar refatoração de código de forma eficiente usando o Claude Code. Inclui prompts práticos e padrões concretos de refatoração para projetos reais.
Guia Completo de Configuração CORS com Claude Code
Aprenda sobre o guia completo de configuração CORS usando o Claude Code. Dicas práticas e exemplos de código incluídos.