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.
PDF gratuito: Cheatsheet do Claude Code em 5 minutos
Basta informar seu e-mail e enviamos na hora o cheatsheet em uma página A4.
Cuidamos dos seus dados pessoais e nunca enviamos spam.
Sobre o autor
Masa
Engenheiro apaixonado por Claude Code. Mantém o claudecode-lab.com, uma mídia tech em 10 idiomas com mais de 2.000 páginas.
Artigos relacionados
7 verificações antes de publicar todos os dias um artigo multilíngue sobre Claude Code
Uma checklist prática para publicar artigos multilíngues sobre Claude Code todos os dias sem esquecer idiomas, quebrar CTAs ou deixar páginas antigas no ar.
O que e Codex Automations? Conteudo, analise e deploy com IA enquanto voce dorme
Guia pratico para usar Codex Automations em analytics, artigos, CTA, deploy e monetizacao.
Desenhe Firestore com Claude Code: comece pelas consultas
Workflow prático para Firestore com Claude Code: schema orientado por consultas, índices, custos, regras de segurança e TypeScript.