diff --git a/src/design-system/composites/CommandPalette/CommandPalette.tsx b/src/design-system/composites/CommandPalette/CommandPalette.tsx index b2c0f66..30e56c5 100644 --- a/src/design-system/composites/CommandPalette/CommandPalette.tsx +++ b/src/design-system/composites/CommandPalette/CommandPalette.tsx @@ -14,6 +14,9 @@ interface CommandPaletteProps { data: SearchResult[] onOpen?: () => void onQueryChange?: (query: string) => void + /** Called when Enter is pressed without the user explicitly selecting a result (arrow keys/click). + * Useful for applying the query as a full-text search filter. */ + onSubmit?: (query: string) => void } const CATEGORY_LABELS: Record = { @@ -64,12 +67,13 @@ function highlightText(text: string, query: string, matchRanges?: [number, numbe return <>{parts} } -export function CommandPalette({ open, onClose, onSelect, data, onOpen, onQueryChange }: CommandPaletteProps) { +export function CommandPalette({ open, onClose, onSelect, data, onOpen, onQueryChange, onSubmit }: CommandPaletteProps) { const [query, setQuery] = useState('') const [activeCategory, setActiveCategory] = useState('all') const [scopeFilters, setScopeFilters] = useState([]) const [focusedIdx, setFocusedIdx] = useState(0) const [expandedId, setExpandedId] = useState(null) + const userNavigated = useRef(false) const inputRef = useRef(null) const listRef = useRef(null) @@ -92,6 +96,7 @@ export function CommandPalette({ open, onClose, onSelect, data, onOpen, onQueryC setQuery('') setFocusedIdx(0) setExpandedId(null) + userNavigated.current = false } }, [open]) @@ -150,15 +155,20 @@ export function CommandPalette({ open, onClose, onSelect, data, onOpen, onQueryC break case 'ArrowDown': e.preventDefault() + userNavigated.current = true setFocusedIdx((i) => Math.min(i + 1, flatResults.length - 1)) break case 'ArrowUp': e.preventDefault() + userNavigated.current = true setFocusedIdx((i) => Math.max(i - 1, 0)) break case 'Enter': e.preventDefault() - if (flatResults[focusedIdx]) { + if (!userNavigated.current && onSubmit && query.trim()) { + onSubmit(query.trim()) + onClose() + } else if (flatResults[focusedIdx]) { onSelect(flatResults[focusedIdx]) onClose() } @@ -213,6 +223,7 @@ export function CommandPalette({ open, onClose, onSelect, data, onOpen, onQueryC onChange={(e) => { setQuery(e.target.value) setFocusedIdx(0) + userNavigated.current = false onQueryChange?.(e.target.value) }} aria-label="Search" @@ -282,7 +293,7 @@ export function CommandPalette({ open, onClose, onSelect, data, onOpen, onQueryC onSelect(result) onClose() }} - onMouseEnter={() => setFocusedIdx(flatIdx)} + onMouseEnter={() => { userNavigated.current = true; setFocusedIdx(flatIdx) }} >
{result.icon && ( @@ -353,7 +364,7 @@ export function CommandPalette({ open, onClose, onSelect, data, onOpen, onQueryC
- Open + Search