diff --git a/src/admin/spotlight/Spotlight.tsx b/src/admin/spotlight/Spotlight.tsx
index 7d3db1966..91cb1f551 100644
--- a/src/admin/spotlight/Spotlight.tsx
+++ b/src/admin/spotlight/Spotlight.tsx
@@ -178,16 +178,7 @@ export function Spotlight({ isClosing = false }: SpotlightProps): ReactNode {
else if (filtered.length > 0) value = filtered[0]!.value
}
- const isLastArg = argMode.argIndex >= args.length - 1
-
- if (isLastArg) {
- // All args filled — run the command
- const fullArgs = { ...argMode.values, [currentArg.id]: value }
- dispatch({ type: 'EXIT_ARG_MODE' })
- void runCommandWithArgs(argMode.command, fullArgs)
- } else {
- dispatch({ type: 'SAVE_ARG_AND_ADVANCE', argId: currentArg.id, value })
- }
+ selectArg(value)
break
}
@@ -302,6 +293,24 @@ export function Spotlight({ isClosing = false }: SpotlightProps): ReactNode {
void runCommand(cmd)
}
+ // ─── Arg selection (shared by keyboard Enter + mouse click) ────────────────
+ // Saves the given arg value and either advances to the next arg or, when the
+ // last arg is filled, exits arg mode and runs the command.
+ const selectArg = (value: string) => {
+ if (!dispatch || !runCommandWithArgs || !argMode) return
+ const args = argMode.command.args ?? []
+ const currentArg = args[argMode.argIndex]
+ if (!currentArg) return
+ const isLastArg = argMode.argIndex >= args.length - 1
+ if (isLastArg) {
+ const fullArgs = { ...argMode.values, [currentArg.id]: value }
+ dispatch({ type: 'EXIT_ARG_MODE' })
+ void runCommandWithArgs(argMode.command, fullArgs)
+ } else {
+ dispatch({ type: 'SAVE_ARG_AND_ADVANCE', argId: currentArg.id, value })
+ }
+ }
+
// Derive input placeholder
const placeholder = (() => {
if (argMode) {
@@ -391,6 +400,7 @@ export function Spotlight({ isClosing = false }: SpotlightProps): ReactNode {
listboxId={listboxId}
highlightedIndex={highlightedIndex}
onHighlightChange={handleHighlightChange}
+ onSelectArg={selectArg}
onRun={handleRun}
activeScopeId={activeScopeId}
/>
diff --git a/src/admin/spotlight/SpotlightResults.tsx b/src/admin/spotlight/SpotlightResults.tsx
index 3d2842c20..539a6badd 100644
--- a/src/admin/spotlight/SpotlightResults.tsx
+++ b/src/admin/spotlight/SpotlightResults.tsx
@@ -92,11 +92,13 @@ function ArgModeResults({
query,
highlightedIndex,
onHighlightChange,
+ onSelectArg,
}: {
argMode: ArgModeState
query: string
highlightedIndex: number
onHighlightChange: (index: number) => void
+ onSelectArg: (value: string) => void
}): ReactNode {
const args = argMode.command.args ?? []
const currentArg = args[argMode.argIndex]
@@ -156,6 +158,7 @@ function ArgModeResults({
role="option"
aria-selected={idx === highlightedIndex}
onMouseEnter={() => onHighlightChange(idx)}
+ onClick={() => onSelectArg(opt.value)}
>
@@ -205,6 +208,7 @@ interface SpotlightResultsProps {
listboxId: string
highlightedIndex: number
onHighlightChange: (index: number) => void
+ onSelectArg: (value: string) => void
onRun: (command: Command) => void
activeScopeId: string
}
@@ -213,6 +217,7 @@ export function SpotlightResults({
listboxId,
highlightedIndex,
onHighlightChange,
+ onSelectArg,
onRun,
activeScopeId,
}: SpotlightResultsProps): ReactNode {
@@ -326,6 +331,7 @@ export function SpotlightResults({
query={query}
highlightedIndex={highlightedIndex}
onHighlightChange={onHighlightChange}
+ onSelectArg={onSelectArg}
/>
)
}
diff --git a/src/admin/spotlight/__tests__/SpotlightResults.test.tsx b/src/admin/spotlight/__tests__/SpotlightResults.test.tsx
index 021634fb9..0eacf106d 100644
--- a/src/admin/spotlight/__tests__/SpotlightResults.test.tsx
+++ b/src/admin/spotlight/__tests__/SpotlightResults.test.tsx
@@ -1,8 +1,9 @@
import { afterEach, describe, expect, it, mock } from 'bun:test'
import React from 'react'
-import { cleanup, render, waitFor } from '@testing-library/react'
+import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { SpotlightInternalContext, type SpotlightInternalContextValue } from '../spotlightContext'
import { SpotlightResults } from '../SpotlightResults'
+import type { Command } from '../types'
import type { SpotlightOpenState } from '../state'
afterEach(() => {
@@ -66,4 +67,53 @@ describe('SpotlightResults', () => {
HTMLElement.prototype.scrollIntoView = originalScrollIntoView
}
})
+
+ it('selects a select-type arg value when its option row is clicked', () => {
+ const onSelectArg = mock(() => {})
+ const command: Command = {
+ id: 'test.cmd',
+ title: 'Test command',
+ group: 'plugins',
+ args: [
+ {
+ id: 'tone',
+ label: 'Tone',
+ type: 'select',
+ options: [
+ { value: 'formal', label: 'Formal' },
+ { value: 'casual', label: 'Casual' },
+ ],
+ },
+ ],
+ }
+
+ const context: SpotlightInternalContextValue = {
+ state: {
+ ...makeOpenState(0),
+ argMode: { command, argIndex: 0, values: {} },
+ },
+ dispatch: () => {},
+ commandContext: null,
+ runCommand: async () => {},
+ runCommandWithArgs: async () => {},
+ }
+
+ render(
+
+ {}}
+ onSelectArg={onSelectArg}
+ onRun={() => {}}
+ activeScopeId="root"
+ />
+ ,
+ )
+
+ fireEvent.click(screen.getByText('Casual'))
+
+ expect(onSelectArg).toHaveBeenCalledTimes(1)
+ expect(onSelectArg).toHaveBeenCalledWith('casual')
+ })
})