// ui_kits/site/CommandPalette.jsx — opens with ":" via Popover API. Konami swaps to plasma. const COMMANDS = [ { id: 'home', label: '→ go home', hint: '/', action: 'route:/' }, { id: 'about', label: '→ about', hint: '/about', action: 'route:/about' }, { id: 'exp', label: '→ experiments', hint: '/experiments', action: 'route:/experiments' }, { id: 'fun', label: '→ fun', hint: '/fun', action: 'route:/fun' }, { id: 'lava', label: 'mode · lava', hint: 'light', action: 'mode:lava' }, { id: 'abyss', label: 'mode · abyss', hint: 'dark', action: 'mode:abyss' }, { id: 'plasma',label: 'mode · plasma', hint: 'demo', action: 'mode:plasma' }, { id: '404', label: '→ break the site', hint: '/lost', action: 'route:/lost' }, ]; const CommandPalette = ({ setRoute, setMode }) => { const popRef = React.useRef(null); const inputRef = React.useRef(null); const [q, setQ] = React.useState(''); const [idx, setIdx] = React.useState(0); React.useEffect(() => { const onKey = (e) => { // Open on `:` (also handle Cmd/Ctrl+K for convention) const target = e.target; const inField = target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable); if (!inField && (e.key === ':' || (e.key === 'k' && (e.metaKey || e.ctrlKey)))) { e.preventDefault(); popRef.current?.showPopover(); setTimeout(() => inputRef.current?.focus(), 0); setQ(''); setIdx(0); } }; addEventListener('keydown', onKey); // Konami → plasma for 10s const seq = ['ArrowUp','ArrowUp','ArrowDown','ArrowDown','ArrowLeft','ArrowRight','ArrowLeft','ArrowRight','b','a']; let pos = 0; const konami = (e) => { if (e.key.toLowerCase() === seq[pos].toLowerCase()) { pos++; if (pos === seq.length) { pos = 0; const prev = document.documentElement.getAttribute('data-mode'); setMode('plasma'); setTimeout(() => setMode(prev || 'lava'), 10000); } } else pos = 0; }; addEventListener('keydown', konami); return () => { removeEventListener('keydown', onKey); removeEventListener('keydown', konami); }; }, [setMode]); const filtered = q ? COMMANDS.filter(c => (c.label + c.hint).toLowerCase().includes(q.toLowerCase())) : COMMANDS; React.useEffect(() => { if (idx >= filtered.length) setIdx(0); }, [filtered.length, idx]); const run = (cmd) => { popRef.current?.hidePopover(); if (cmd.action.startsWith('route:')) setRoute(cmd.action.slice(6)); if (cmd.action.startsWith('mode:')) setMode(cmd.action.slice(5)); }; return (
{ if (e.key === 'ArrowDown') { e.preventDefault(); setIdx(i => Math.min(filtered.length - 1, i + 1)); } if (e.key === 'ArrowUp') { e.preventDefault(); setIdx(i => Math.max(0, i - 1)); } if (e.key === 'Enter' && filtered[idx]) run(filtered[idx]); if (e.key === 'Escape') popRef.current?.hidePopover(); }}>
: setQ(e.target.value)} placeholder="type a command…" autoFocus />
); }; window.CommandPalette = CommandPalette;