summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/components
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-03-10 11:29:57 -0500
committerAdam <[email protected]>2026-03-10 13:00:14 -0500
commit835a27cf517fae5d9952c30989de8be8f760d7a5 (patch)
tree94c5ec763e09517d42ce86a960264854c139f2f3 /packages/app/src/components
parent85afaaa13d693f400d8ec8e257fec086a58b68c1 (diff)
downloadopencode-835a27cf517fae5d9952c30989de8be8f760d7a5.tar.gz
opencode-835a27cf517fae5d9952c30989de8be8f760d7a5.zip
fix(app): terminal jank
Diffstat (limited to 'packages/app/src/components')
-rw-r--r--packages/app/src/components/session/session-header.tsx75
-rw-r--r--packages/app/src/components/terminal.tsx5
2 files changed, 47 insertions, 33 deletions
diff --git a/packages/app/src/components/session/session-header.tsx b/packages/app/src/components/session/session-header.tsx
index 9b4551584..97f0530e9 100644
--- a/packages/app/src/components/session/session-header.tsx
+++ b/packages/app/src/components/session/session-header.tsx
@@ -21,6 +21,8 @@ import { useLayout } from "@/context/layout"
import { usePlatform } from "@/context/platform"
import { useServer } from "@/context/server"
import { useSync } from "@/context/sync"
+import { useTerminal } from "@/context/terminal"
+import { focusTerminalById } from "@/pages/session/helpers"
import { decode64 } from "@/utils/base64"
import { Persist, persisted } from "@/utils/persist"
import { StatusPopover } from "../status-popover"
@@ -229,6 +231,7 @@ export function SessionHeader() {
const sync = useSync()
const platform = usePlatform()
const language = useLanguage()
+ const terminal = useTerminal()
const projectDirectory = createMemo(() => decode64(params.dir) ?? "")
const project = createMemo(() => {
@@ -296,6 +299,16 @@ export function SessionHeader() {
] as const
})
+ const toggleTerminal = () => {
+ const next = !view().terminal.opened()
+ view().terminal.toggle()
+ if (!next) return
+
+ const id = terminal.active()
+ if (!id) return
+ focusTerminalById(id)
+ }
+
const [prefs, setPrefs] = persisted(Persist.global("open.app"), createStore({ app: "finder" as OpenApp }))
const [menu, setMenu] = createStore({ open: false })
const [openRequest, setOpenRequest] = createStore({
@@ -617,39 +630,39 @@ export function SessionHeader() {
</div>
</Show>
<div class="flex items-center gap-1">
- <div class="hidden md:flex items-center gap-1 shrink-0">
- <TooltipKeybind
- title={language.t("command.terminal.toggle")}
- keybind={command.keybind("terminal.toggle")}
+ <TooltipKeybind
+ title={language.t("command.terminal.toggle")}
+ keybind={command.keybind("terminal.toggle")}
+ >
+ <Button
+ variant="ghost"
+ class="group/terminal-toggle titlebar-icon w-8 h-6 p-0 box-border shrink-0"
+ onClick={toggleTerminal}
+ aria-label={language.t("command.terminal.toggle")}
+ aria-expanded={view().terminal.opened()}
+ aria-controls="terminal-panel"
>
- <Button
- variant="ghost"
- class="group/terminal-toggle titlebar-icon w-8 h-6 p-0 box-border"
- onClick={() => view().terminal.toggle()}
- aria-label={language.t("command.terminal.toggle")}
- aria-expanded={view().terminal.opened()}
- aria-controls="terminal-panel"
- >
- <div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
- <Icon
- size="small"
- name={view().terminal.opened() ? "layout-bottom-partial" : "layout-bottom"}
- class="group-hover/terminal-toggle:hidden"
- />
- <Icon
- size="small"
- name="layout-bottom-partial"
- class="hidden group-hover/terminal-toggle:inline-block"
- />
- <Icon
- size="small"
- name={view().terminal.opened() ? "layout-bottom" : "layout-bottom-partial"}
- class="hidden group-active/terminal-toggle:inline-block"
- />
- </div>
- </Button>
- </TooltipKeybind>
+ <div class="relative flex items-center justify-center size-4 [&>*]:absolute [&>*]:inset-0">
+ <Icon
+ size="small"
+ name={view().terminal.opened() ? "layout-bottom-partial" : "layout-bottom"}
+ class="group-hover/terminal-toggle:hidden"
+ />
+ <Icon
+ size="small"
+ name="layout-bottom-partial"
+ class="hidden group-hover/terminal-toggle:inline-block"
+ />
+ <Icon
+ size="small"
+ name={view().terminal.opened() ? "layout-bottom" : "layout-bottom-partial"}
+ class="hidden group-active/terminal-toggle:inline-block"
+ />
+ </div>
+ </Button>
+ </TooltipKeybind>
+ <div class="hidden md:flex items-center gap-1 shrink-0">
<TooltipKeybind
title={language.t("command.review.toggle")}
keybind={command.keybind("review.toggle")}
diff --git a/packages/app/src/components/terminal.tsx b/packages/app/src/components/terminal.tsx
index 9e5f12ee4..120af0a17 100644
--- a/packages/app/src/components/terminal.tsx
+++ b/packages/app/src/components/terminal.tsx
@@ -17,6 +17,7 @@ const TOGGLE_TERMINAL_ID = "terminal.toggle"
const DEFAULT_TOGGLE_TERMINAL_KEYBIND = "ctrl+`"
export interface TerminalProps extends ComponentProps<"div"> {
pty: LocalPTY
+ autoFocus?: boolean
onSubmit?: () => void
onCleanup?: (pty: Partial<LocalPTY> & { id: string }) => void
onConnect?: () => void
@@ -157,7 +158,7 @@ export const Terminal = (props: TerminalProps) => {
const language = useLanguage()
const server = useServer()
let container!: HTMLDivElement
- const [local, others] = splitProps(props, ["pty", "class", "classList", "onConnect", "onConnectError"])
+ const [local, others] = splitProps(props, ["pty", "class", "classList", "autoFocus", "onConnect", "onConnectError"])
const id = local.pty.id
const restore = typeof local.pty.buffer === "string" ? local.pty.buffer : ""
const restoreSize =
@@ -386,7 +387,7 @@ export const Terminal = (props: TerminalProps) => {
handleLinkClick,
})
- focusTerminal()
+ if (local.autoFocus !== false) focusTerminal()
if (typeof document !== "undefined" && document.fonts) {
document.fonts.ready.then(scheduleFit)