summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/context/command.tsx
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-01-15 17:58:17 -0600
committerAdam <[email protected]>2026-01-15 17:59:26 -0600
commit657f3d5089cc20315ead234367ee8f1f18efd754 (patch)
tree23d25ef7dfce2ff3d9fad802d8727e20f4cd777b /packages/app/src/context/command.tsx
parent49939c4d8d4b7112273ab03779d4ec0c9ad2a175 (diff)
downloadopencode-657f3d5089cc20315ead234367ee8f1f18efd754.tar.gz
opencode-657f3d5089cc20315ead234367ee8f1f18efd754.zip
feat(app): unified search for commands and files
Diffstat (limited to 'packages/app/src/context/command.tsx')
-rw-r--r--packages/app/src/context/command.tsx81
1 files changed, 12 insertions, 69 deletions
diff --git a/packages/app/src/context/command.tsx b/packages/app/src/context/command.tsx
index 7f88b74c8..3c640d8e9 100644
--- a/packages/app/src/context/command.tsx
+++ b/packages/app/src/context/command.tsx
@@ -1,8 +1,5 @@
-import { createMemo, createSignal, onCleanup, onMount, Show, type Accessor } from "solid-js"
+import { createMemo, createSignal, onCleanup, onMount, type Accessor } from "solid-js"
import { createSimpleContext } from "@opencode-ai/ui/context"
-import { useDialog } from "@opencode-ai/ui/context/dialog"
-import { Dialog } from "@opencode-ai/ui/dialog"
-import { List } from "@opencode-ai/ui/list"
const IS_MAC = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform)
@@ -114,67 +111,11 @@ export function formatKeybind(config: string): string {
return IS_MAC ? parts.join("") : parts.join("+")
}
-function DialogCommand(props: { options: CommandOption[] }) {
- const dialog = useDialog()
- let cleanup: (() => void) | void
- let committed = false
-
- const handleMove = (option: CommandOption | undefined) => {
- cleanup?.()
- cleanup = option?.onHighlight?.()
- }
-
- const handleSelect = (option: CommandOption | undefined) => {
- if (option) {
- committed = true
- cleanup = undefined
- dialog.close()
- option.onSelect?.("palette")
- }
- }
-
- onCleanup(() => {
- if (!committed) {
- cleanup?.()
- }
- })
-
- return (
- <Dialog title="Commands">
- <List
- search={{ placeholder: "Search commands", autofocus: true }}
- emptyMessage="No commands found"
- items={() => props.options.filter((x) => !x.id.startsWith("suggested.") || !x.disabled)}
- key={(x) => x?.id}
- filterKeys={["title", "description", "category"]}
- groupBy={(x) => x.category ?? ""}
- onMove={handleMove}
- onSelect={handleSelect}
- >
- {(option) => (
- <div class="w-full flex items-center justify-between gap-4">
- <div class="flex items-center gap-2 min-w-0">
- <span class="text-14-regular text-text-strong whitespace-nowrap">{option.title}</span>
- <Show when={option.description}>
- <span class="text-14-regular text-text-weak truncate">{option.description}</span>
- </Show>
- </div>
- <Show when={option.keybind}>
- <span class="text-12-regular text-text-subtle shrink-0">{formatKeybind(option.keybind!)}</span>
- </Show>
- </div>
- )}
- </List>
- </Dialog>
- )
-}
-
export const { use: useCommand, provider: CommandProvider } = createSimpleContext({
name: "Command",
init: () => {
const [registrations, setRegistrations] = createSignal<Accessor<CommandOption[]>[]>([])
const [suspendCount, setSuspendCount] = createSignal(0)
- const dialog = useDialog()
const options = createMemo(() => {
const seen = new Set<string>()
@@ -202,12 +143,19 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex
const suspended = () => suspendCount() > 0
- const showPalette = () => {
- if (!dialog.active) {
- dialog.show(() => <DialogCommand options={options().filter((x) => !x.disabled)} />)
+ const run = (id: string, source?: "palette" | "keybind" | "slash") => {
+ for (const option of options()) {
+ if (option.id === id || option.id === "suggested." + id) {
+ option.onSelect?.(source)
+ return
+ }
}
}
+ const showPalette = () => {
+ run("file.open", "palette")
+ }
+
const handleKeyDown = (event: KeyboardEvent) => {
if (suspended()) return
@@ -248,12 +196,7 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex
})
},
trigger(id: string, source?: "palette" | "keybind" | "slash") {
- for (const option of options()) {
- if (option.id === id || option.id === "suggested." + id) {
- option.onSelect?.(source)
- return
- }
- }
+ run(id, source)
},
keybind(id: string) {
const option = options().find((x) => x.id === id || x.id === "suggested." + id)