Use Cases

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.

#Claude Code #コマンドパレット #UI #キーボード操作 #React