summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/components
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-02-17 15:53:38 -0600
committerGitHub <[email protected]>2026-02-17 15:53:38 -0600
commitd327a2b1cf750a7552d149078658fdc8ad037171 (patch)
tree7711236d05cd7377af0d1118c85fe1300f6b18dd /packages/app/src/components
parentc1b03b728af259a1556dc39db58e162b382527b3 (diff)
downloadopencode-d327a2b1cf750a7552d149078658fdc8ad037171.tar.gz
opencode-d327a2b1cf750a7552d149078658fdc8ad037171.zip
chore(app): use radio group in prompt input (#14025)
Diffstat (limited to 'packages/app/src/components')
-rw-r--r--packages/app/src/components/prompt-input.tsx89
1 files changed, 49 insertions, 40 deletions
diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx
index ca7cc0325..dcd5bd2f1 100644
--- a/packages/app/src/components/prompt-input.tsx
+++ b/packages/app/src/components/prompt-input.tsx
@@ -1,5 +1,5 @@
import { useFilteredList } from "@opencode-ai/ui/hooks"
-import { createEffect, on, Component, Show, For, onCleanup, Switch, Match, createMemo, createSignal } from "solid-js"
+import { createEffect, on, Component, Show, onCleanup, Switch, Match, createMemo, createSignal } from "solid-js"
import { createStore } from "solid-js/store"
import { createFocusSignal } from "@solid-primitives/active-element"
import { useLocal } from "@/context/local"
@@ -26,6 +26,7 @@ import type { IconName } from "@opencode-ai/ui/icons/provider"
import { Tooltip, TooltipKeybind } from "@opencode-ai/ui/tooltip"
import { IconButton } from "@opencode-ai/ui/icon-button"
import { Select } from "@opencode-ai/ui/select"
+import { RadioGroup } from "@opencode-ai/ui/radio-group"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { ModelSelectorPopover } from "@/components/dialog-select-model"
import { DialogSelectModelUnpaid } from "@/components/dialog-select-model-unpaid"
@@ -249,7 +250,6 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
return messages.some((m) => m.role === "user")
})
- const MAX_HISTORY = 100
const [history, setHistory] = persisted(
Persist.global("prompt-history", ["prompt-history.v1"]),
createStore<{
@@ -319,6 +319,9 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
requestAnimationFrame(() => editorRef?.focus())
}
+ const shellModeKey = "mod+shift+x"
+ const normalModeKey = "mod+shift+e"
+
command.register("prompt-input", () => [
{
id: "file.attach",
@@ -328,6 +331,22 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
disabled: store.mode !== "normal",
onSelect: pick,
},
+ {
+ id: "prompt.mode.shell",
+ title: language.t("command.prompt.mode.shell"),
+ category: language.t("command.category.session"),
+ keybind: shellModeKey,
+ disabled: store.mode === "shell",
+ onSelect: () => setMode("shell"),
+ },
+ {
+ id: "prompt.mode.normal",
+ title: language.t("command.prompt.mode.normal"),
+ category: language.t("command.category.session"),
+ keybind: normalModeKey,
+ disabled: store.mode === "normal",
+ onSelect: () => setMode("normal"),
+ },
])
const closePopover = () => setStore("popover", null)
@@ -1339,45 +1358,35 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
</TooltipKeybind>
</Show>
</div>
-
- <div class="shrink-0">
- <div
- data-component="prompt-mode-toggle"
- class="relative h-7 w-[68px] rounded-[4px] bg-surface-inset-base border border-[0.5px] border-border-weak-base p-0 flex items-center gap-1 overflow-visible"
- >
- <div
- class="absolute inset-y-0 left-0 w-[calc((100%-4px)/2)] rounded-[4px] bg-surface-raised-stronger-non-alpha shadow-[var(--shadow-xs-border)] transition-transform duration-200 ease-out will-change-transform"
- style={{
- transform: store.mode === "shell" ? "translateX(0px)" : "translateX(calc(100% + 4px))",
- }}
- />
- <button
- type="button"
- class="relative z-10 flex-1 h-full p-0.5 flex items-center justify-center"
- aria-pressed={store.mode === "shell"}
- onClick={() => setMode("shell")}
- >
- <div
- class="w-full h-full flex items-center justify-center rounded-[2px] transition-colors hover:bg-surface-inset-base"
- classList={{ "hover:bg-transparent": store.mode === "shell" }}
- >
- <Icon name="console" class="size-[18px]" />
- </div>
- </button>
- <button
- type="button"
- class="relative z-10 flex-1 h-full p-0.5 flex items-center justify-center"
- aria-pressed={store.mode === "normal"}
- onClick={() => setMode("normal")}
- >
- <div
- class="w-full h-full flex items-center justify-center rounded-[2px] transition-colors hover:bg-surface-inset-base"
- classList={{ "hover:bg-transparent": store.mode === "normal" }}
+ <div class="shrink-0" data-component="prompt-mode-toggle">
+ <RadioGroup
+ options={["shell", "normal"] as const}
+ current={store.mode}
+ value={(mode) => mode}
+ label={(mode) => (
+ <TooltipKeybind
+ placement="top"
+ gutter={4}
+ title={language.t(mode === "shell" ? "command.prompt.mode.shell" : "command.prompt.mode.normal")}
+ keybind={command.keybind(mode === "shell" ? "prompt.mode.shell" : "prompt.mode.normal")}
+ class="size-full flex items-center justify-center"
>
- <Icon name="prompt" class="size-[18px]" />
- </div>
- </button>
- </div>
+ <Icon
+ name={mode === "shell" ? "console" : "prompt"}
+ class="size-[18px]"
+ classList={{
+ "text-icon-strong-base": mode === "shell" && store.mode === "shell",
+ "text-icon-interactive-base": mode === "normal" && store.mode === "normal",
+ "text-icon-weak": store.mode !== mode,
+ }}
+ />
+ </TooltipKeybind>
+ )}
+ onSelect={(mode) => mode && setMode(mode)}
+ fill
+ pad="none"
+ class="w-[68px]"
+ />
</div>
</div>
</div>