summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-01-04 23:28:03 -0600
committerAdam <[email protected]>2026-01-05 13:21:30 -0600
commitd315026abc0a07e88b3bec6b74253e272161659b (patch)
tree5f57c5beeb753492e0780654576ca645a44896de
parentd1191675c68d8995333fc4300b11d09e87d711d2 (diff)
downloadopencode-d315026abc0a07e88b3bec6b74253e272161659b.tar.gz
opencode-d315026abc0a07e88b3bec6b74253e272161659b.zip
fix(app): prompt input shouldn't cover content
-rw-r--r--packages/app/src/components/session/session-new-view.tsx5
-rw-r--r--packages/app/src/pages/session.tsx39
2 files changed, 39 insertions, 5 deletions
diff --git a/packages/app/src/components/session/session-new-view.tsx b/packages/app/src/components/session/session-new-view.tsx
index 81d719471..68ef0cc1f 100644
--- a/packages/app/src/components/session/session-new-view.tsx
+++ b/packages/app/src/components/session/session-new-view.tsx
@@ -44,7 +44,10 @@ export function NewSessionView(props: NewSessionViewProps) {
}
return (
- <div class="size-full flex flex-col pb-45 justify-end items-start gap-4 flex-[1_0_0] self-stretch max-w-200 mx-auto px-6">
+ <div
+ class="size-full flex flex-col pb-45 justify-end items-start gap-4 flex-[1_0_0] self-stretch max-w-200 mx-auto px-6"
+ style={{ "padding-bottom": "calc(var(--prompt-height, 11.25rem) + 64px)" }}
+ >
<div class="text-20-medium text-text-weaker">New session</div>
<div class="flex justify-center items-center gap-3">
<Icon name="folder" size="small" />
diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx
index be500afd3..3c23ac61e 100644
--- a/packages/app/src/pages/session.tsx
+++ b/packages/app/src/pages/session.tsx
@@ -1,5 +1,6 @@
import { For, onCleanup, Show, Match, Switch, createMemo, createEffect, on } from "solid-js"
import { createMediaQuery } from "@solid-primitives/media"
+import { createResizeObserver } from "@solid-primitives/resize-observer"
import { Dynamic } from "solid-js/web"
import { useLocal } from "@/context/local"
import { selectionFromLines, useFile, type SelectedLineRange } from "@/context/file"
@@ -248,6 +249,7 @@ export default function Page() {
messageId: undefined as string | undefined,
mobileTab: "session" as "session" | "review",
newSessionWorktree: "main",
+ promptHeight: 0,
})
const newSessionWorktree = createMemo(() => {
@@ -289,6 +291,8 @@ export default function Page() {
const idle = { type: "idle" as const }
let inputRef!: HTMLDivElement
+ let promptDock: HTMLDivElement | undefined
+ let scroller: HTMLDivElement | undefined
createEffect(() => {
if (!params.id) return
@@ -668,9 +672,30 @@ export default function Page() {
const anchor = (id: string) => `message-${id}`
const setScrollRef = (el: HTMLDivElement | undefined) => {
+ scroller = el
autoScroll.scrollRef(el)
}
+ createResizeObserver(
+ () => promptDock,
+ ({ height }) => {
+ const next = Math.ceil(height)
+
+ if (next === store.promptHeight) return
+
+ const el = scroller
+ const stick = el ? el.scrollHeight - el.clientHeight - el.scrollTop < 10 : false
+
+ setStore("promptHeight", next)
+
+ if (stick && el) {
+ requestAnimationFrame(() => {
+ el.scrollTo({ top: el.scrollHeight, behavior: "auto" })
+ })
+ }
+ },
+ )
+
const updateHash = (id: string) => {
window.history.replaceState(null, "", `#${anchor(id)}`)
}
@@ -776,7 +801,10 @@ export default function Page() {
"@container relative shrink-0 flex flex-col min-h-0 h-full bg-background-stronger": true,
"flex-1 md:flex-none py-6 md:py-3": true,
}}
- style={{ width: isDesktop() && showTabs() ? `${layout.session.width()}px` : "100%" }}
+ style={{
+ width: isDesktop() && showTabs() ? `${layout.session.width()}px` : "100%",
+ "--prompt-height": store.promptHeight ? `${store.promptHeight}px` : undefined,
+ }}
>
<div class="flex-1 min-h-0 overflow-hidden">
<Switch>
@@ -791,7 +819,7 @@ export default function Page() {
view={view}
diffStyle="unified"
classes={{
- root: "pb-32",
+ root: "pb-[calc(var(--prompt-height,8rem)+32px)]",
header: "px-4",
container: "px-4",
}}
@@ -822,7 +850,7 @@ export default function Page() {
>
<div
ref={autoScroll.contentRef}
- class="flex flex-col gap-32 items-start justify-start pb-32 md:pb-40 transition-[margin]"
+ class="flex flex-col gap-32 items-start justify-start pb-[calc(var(--prompt-height,8rem)+64px)] md:pb-[calc(var(--prompt-height,10rem)+64px)] transition-[margin]"
classList={{
"mt-0.5": !showTabs(),
"mt-0": showTabs(),
@@ -894,7 +922,10 @@ export default function Page() {
</div>
{/* Prompt input */}
- <div class="absolute inset-x-0 bottom-0 pt-12 pb-4 md:pb-8 flex flex-col justify-center items-center z-50 px-4 md:px-0 bg-gradient-to-t from-background-stronger via-background-stronger to-transparent pointer-events-none">
+ <div
+ ref={(el) => (promptDock = el)}
+ class="absolute inset-x-0 bottom-0 pt-12 pb-4 md:pb-8 flex flex-col justify-center items-center z-50 px-4 md:px-0 bg-gradient-to-t from-background-stronger via-background-stronger to-transparent pointer-events-none"
+ >
<div
classList={{
"w-full md:px-6 pointer-events-auto": true,