diff options
| author | David Hill <[email protected]> | 2026-03-13 15:48:10 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-03-13 10:48:10 -0500 |
| commit | 5c7088338c07ad632834ebd4a87feb23d255fb8a (patch) | |
| tree | 66e378a6d8bb71642b2d594e221a1856e1e42429 | |
| parent | 389daa03df9ba591b4629655e77c9229ec3fa184 (diff) | |
| download | opencode-5c7088338c07ad632834ebd4a87feb23d255fb8a.tar.gz opencode-5c7088338c07ad632834ebd4a87feb23d255fb8a.zip | |
fix(app): polish prompt composer controls (#17388)
| -rw-r--r-- | packages/app/src/components/prompt-input.tsx | 123 | ||||
| -rw-r--r-- | packages/ui/src/components/icon.tsx | 1 |
2 files changed, 60 insertions, 64 deletions
diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 3b78e8033..fd54de9a0 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -121,7 +121,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => { let slashPopoverRef!: HTMLDivElement const mirror = { input: false } - const inset = 52 + const inset = 56 const space = `${inset}px` const scrollCursorIntoView = () => { @@ -1031,6 +1031,17 @@ export const PromptInput: Component<PromptInputProps> = (props) => { if (!id) return permission.isAutoAcceptingDirectory(sdk.directory) return permission.isAutoAccepting(id, sdk.directory) }) + const acceptLabel = createMemo(() => + language.t(accepting() ? "command.permissions.autoaccept.disable" : "command.permissions.autoaccept.enable"), + ) + const toggleAccept = () => { + if (!params.id) { + permission.toggleAutoAcceptDirectory(sdk.directory) + return + } + + permission.toggleAutoAccept(params.id, sdk.directory) + } const { abort, handleSubmit } = createPromptSubmit({ info, @@ -1337,33 +1348,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => { }} /> - <div - aria-hidden={store.mode !== "normal"} - class="flex items-center gap-1" - style={{ - "pointer-events": buttonsSpring() > 0.5 ? "auto" : "none", - }} - > - <TooltipKeybind - placement="top" - title={language.t("prompt.action.attachFile")} - keybind={command.keybind("file.attach")} - > - <Button - data-action="prompt-attach" - type="button" - variant="ghost" - class="size-8 p-0" - style={buttons()} - onClick={pick} - disabled={store.mode !== "normal"} - tabIndex={store.mode === "normal" ? undefined : -1} - aria-label={language.t("prompt.action.attachFile")} - > - <Icon name="plus" class="size-4.5" /> - </Button> - </TooltipKeybind> - + <div class="flex items-center gap-1 pointer-events-auto"> <Tooltip placement="top" inactive={!prompt.dirty() && !working()} @@ -1400,42 +1385,30 @@ export const PromptInput: Component<PromptInputProps> = (props) => { </div> <div class="pointer-events-none absolute bottom-2 left-2"> - <div class="pointer-events-auto"> + <div + aria-hidden={store.mode !== "normal"} + class="pointer-events-auto" + style={{ + "pointer-events": buttonsSpring() > 0.5 ? "auto" : "none", + }} + > <TooltipKeybind placement="top" - gutter={8} - title={language.t( - accepting() ? "command.permissions.autoaccept.disable" : "command.permissions.autoaccept.enable", - )} - keybind={command.keybind("permissions.autoaccept")} + title={language.t("prompt.action.attachFile")} + keybind={command.keybind("file.attach")} > <Button - data-action="prompt-permissions" + data-action="prompt-attach" + type="button" variant="ghost" - onClick={() => { - if (!params.id) { - permission.toggleAutoAcceptDirectory(sdk.directory) - return - } - permission.toggleAutoAccept(params.id, sdk.directory) - }} - classList={{ - "size-6 flex items-center justify-center": true, - "text-text-base": !accepting(), - "hover:bg-surface-success-base": accepting(), - }} - aria-label={ - accepting() - ? language.t("command.permissions.autoaccept.disable") - : language.t("command.permissions.autoaccept.enable") - } - aria-pressed={accepting()} + class="size-8 p-0" + style={buttons()} + onClick={pick} + disabled={store.mode !== "normal"} + tabIndex={store.mode === "normal" ? undefined : -1} + aria-label={language.t("prompt.action.attachFile")} > - <Icon - name="chevron-double-right" - size="small" - classList={{ "text-icon-success-base": accepting() }} - /> + <Icon name="plus" class="size-4.5" /> </Button> </TooltipKeybind> </div> @@ -1468,8 +1441,8 @@ export const PromptInput: Component<PromptInputProps> = (props) => { options={agentNames()} current={local.agent.current()?.name ?? ""} onSelect={local.agent.set} - class="capitalize max-w-[160px]" - valueClass="truncate text-13-regular" + class="capitalize max-w-[160px] text-text-base" + valueClass="truncate text-13-regular text-text-base" triggerStyle={control()} variant="ghost" /> @@ -1487,7 +1460,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => { as="div" variant="ghost" size="normal" - class="min-w-0 max-w-[320px] text-13-regular group" + class="min-w-0 max-w-[320px] text-13-regular text-text-base group" style={control()} onClick={() => dialog.show(() => <DialogSelectModelUnpaid />)} > @@ -1518,7 +1491,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => { variant: "ghost", size: "normal", style: control(), - class: "min-w-0 max-w-[320px] text-13-regular group", + class: "min-w-0 max-w-[320px] text-13-regular text-text-base group", }} > <Show when={local.model.current()?.provider?.id}> @@ -1547,12 +1520,34 @@ export const PromptInput: Component<PromptInputProps> = (props) => { current={local.model.variant.current() ?? "default"} label={(x) => (x === "default" ? language.t("common.default") : x)} onSelect={(x) => local.model.variant.set(x === "default" ? undefined : x)} - class="capitalize max-w-[160px]" - valueClass="truncate text-13-regular" + class="capitalize max-w-[160px] text-text-base" + valueClass="truncate text-13-regular text-text-base" triggerStyle={control()} variant="ghost" /> </TooltipKeybind> + <TooltipKeybind + placement="top" + gutter={8} + title={acceptLabel()} + keybind={command.keybind("permissions.autoaccept")} + > + <Button + data-action="prompt-permissions" + variant="ghost" + onClick={toggleAccept} + classList={{ + "h-7 w-7 p-0 shrink-0 flex items-center justify-center": true, + "text-text-base": !accepting(), + "hover:bg-surface-success-base": accepting(), + }} + style={control()} + aria-label={acceptLabel()} + aria-pressed={accepting()} + > + <Icon name="shield" size="small" classList={{ "text-icon-success-base": accepting() }} /> + </Button> + </TooltipKeybind> </div> </div> </div> diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index aacfa476b..e2eaf107a 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -82,6 +82,7 @@ const icons = { check: `<path d="M5 11.9657L8.37838 14.7529L15 5.83398" stroke="currentColor" stroke-linecap="square"/>`, photo: `<path d="M16.6665 16.6666L11.6665 11.6666L9.99984 13.3333L6.6665 9.99996L3.08317 13.5833M2.9165 2.91663H17.0832V17.0833H2.9165V2.91663ZM13.3332 7.49996C13.3332 8.30537 12.6803 8.95829 11.8748 8.95829C11.0694 8.95829 10.4165 8.30537 10.4165 7.49996C10.4165 6.69454 11.0694 6.04163 11.8748 6.04163C12.6803 6.04163 13.3332 6.69454 13.3332 7.49996Z" stroke="currentColor" stroke-linecap="square"/>`, share: `<path d="M10.0013 12.0846L10.0013 3.33464M13.7513 6.66797L10.0013 2.91797L6.2513 6.66797M17.0846 10.418V17.0846H2.91797V10.418" stroke="currentColor" stroke-linecap="square"/>`, + shield: `<path d="M7.49935 9.3737L9.16602 11.0404L12.4994 7.70703M9.99935 2.08203L17.0827 4.3737V9.92565C17.0827 14.0694 13.3327 16.2487 9.99935 18.047C6.66602 16.2487 2.91602 14.0694 2.91602 9.92565V4.3737L9.99935 2.08203Z" stroke="currentColor" stroke-linecap="square"/>`, download: `<path d="M13.9583 10.6257L10 14.584L6.04167 10.6257M10 2.08398V13.959M16.25 17.9173H3.75" stroke="currentColor" stroke-linecap="square"/>`, menu: `<path d="M2.5 5H17.5M2.5 10H17.5M2.5 15H17.5" stroke="currentColor" stroke-linecap="square"/>`, server: `<rect x="3.35547" y="1.92969" width="13.2857" height="16.1429" stroke="currentColor"/><rect x="3.35547" y="11.9297" width="13.2857" height="6.14286" stroke="currentColor"/><rect x="12.8555" y="14.2852" width="1.42857" height="1.42857" fill="currentColor"/><rect x="10" y="14.2852" width="1.42857" height="1.42857" fill="currentColor"/>`, |
