Skip to content

Commit 89bb1bf

Browse files
committed
fix(app): expose context pane on mobile web
* workaround tooltip ignoring touch events * introduce third mobile tab state for context panel * two-tap pattern for opening context tab from tooltip
1 parent b24fd90 commit 89bb1bf

File tree

5 files changed

+221
-161
lines changed

5 files changed

+221
-161
lines changed

packages/app/src/components/session-context-usage.tsx

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Match, Show, Switch, createMemo } from "solid-js"
1+
import { Match, Show, Switch, createMemo, createSignal, onCleanup } from "solid-js"
22
import { Tooltip } from "@opencode-ai/ui/tooltip"
33
import { ProgressCircle } from "@opencode-ai/ui/progress-circle"
44
import { Button } from "@opencode-ai/ui/button"
@@ -14,11 +14,17 @@ interface SessionContextUsageProps {
1414
variant?: "button" | "indicator"
1515
}
1616

17+
const isTouch = () => window.matchMedia("(hover: none)").matches
18+
1719
export function SessionContextUsage(props: SessionContextUsageProps) {
1820
const sync = useSync()
1921
const params = useParams()
2022
const layout = useLayout()
2123
const language = useLanguage()
24+
const [touchTooltip, setTouchTooltip] = createSignal(false)
25+
let tooltipTimer: number | undefined
26+
27+
onCleanup(() => clearTimeout(tooltipTimer))
2228

2329
const variant = createMemo(() => props.variant ?? "button")
2430
const sessionKey = createMemo(() => `${params.dir}${params.id ? "/" + params.id : ""}`)
@@ -59,10 +65,30 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
5965
const openContext = () => {
6066
if (!params.id) return
6167
view().reviewPanel.open()
68+
view().mobileTab.set("context")
6269
tabs().open("context")
6370
tabs().setActive("context")
6471
}
6572

73+
const handleClick = () => {
74+
if (variant() === "indicator") return
75+
if (isTouch() && !touchTooltip()) {
76+
setTouchTooltip(true)
77+
clearTimeout(tooltipTimer)
78+
tooltipTimer = window.setTimeout(() => setTouchTooltip(false), 3000)
79+
return
80+
}
81+
setTouchTooltip(false)
82+
openContext()
83+
}
84+
85+
const handleOpenChange = (open: boolean) => {
86+
// On touch devices, we control the tooltip state ourselves via handleClick
87+
// Ignore Kobalte's attempts to close it
88+
if (isTouch()) return
89+
setTouchTooltip(open)
90+
}
91+
6692
const circle = () => (
6793
<div class="p-1">
6894
<ProgressCircle size={16} strokeWidth={2} percentage={context()?.percentage ?? 0} />
@@ -94,15 +120,20 @@ export function SessionContextUsage(props: SessionContextUsageProps) {
94120

95121
return (
96122
<Show when={params.id}>
97-
<Tooltip value={tooltipValue()} placement="top">
123+
<Tooltip
124+
value={tooltipValue()}
125+
placement="top"
126+
open={touchTooltip() || undefined}
127+
onOpenChange={handleOpenChange}
128+
>
98129
<Switch>
99130
<Match when={variant() === "indicator"}>{circle()}</Match>
100131
<Match when={true}>
101132
<Button
102133
type="button"
103134
variant="ghost"
104135
class="size-6"
105-
onClick={openContext}
136+
onClick={handleClick}
106137
aria-label={language.t("context.usage.view")}
107138
>
108139
{circle()}

packages/app/src/components/session/session-context-tab.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,14 +367,14 @@ export function SessionContextTab(props: SessionContextTabProps) {
367367

368368
return (
369369
<div
370-
class="@container h-full overflow-y-auto no-scrollbar pb-10"
370+
class="@container h-full overflow-y-auto no-scrollbar md:pb-10 pb-[calc(var(--prompt-height,6rem)+32px)]"
371371
ref={(el) => {
372372
scroll = el
373373
restoreScroll()
374374
}}
375375
onScroll={handleScroll}
376376
>
377-
<div class="px-6 pt-4 flex flex-col gap-10">
377+
<div class="px-4 md:px-6 pt-4 flex flex-col gap-10">
378378
<div class="grid grid-cols-1 @[32rem]:grid-cols-2 gap-4">
379379
<For each={stats()}>{(stat) => <Stat label={stat.label} value={stat.value} />}</For>
380380
</div>

packages/app/src/context/layout.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
9292
mobileSidebar: {
9393
opened: false,
9494
},
95+
mobileTab: "session" as "session" | "review" | "context",
9596
sessionTabs: {} as Record<string, SessionTabs>,
9697
sessionView: {} as Record<string, SessionView>,
9798
}),
@@ -600,6 +601,12 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
600601
setStore("sessionView", session, "reviewOpen", open)
601602
},
602603
},
604+
mobileTab: {
605+
value: createMemo(() => store.mobileTab),
606+
set(tab: "session" | "review" | "context") {
607+
setStore("mobileTab", tab)
608+
},
609+
},
603610
}
604611
},
605612
tabs(sessionKey: string | Accessor<string>) {

0 commit comments

Comments
 (0)