Skip to content

Commit 9ae229f

Browse files
Merge pull request #448 from chriswritescode-dev/fix/form-prompt-desktop-overflow
fix(sessions): keep the question card within the space above the prompt
2 parents 32a2cd1 + 24ac88e commit 9ae229f

5 files changed

Lines changed: 32 additions & 17 deletions

File tree

‎frontend/src/components/repo/RepoList.tsx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,12 @@ export function RepoList() {
308308
switch (true) {
309309
case isLoading && !repos:
310310
return (
311-
<div className="px-0 md:p-4 h-full flex flex-col">
311+
<div className="px-0 md:px-4 md:pt-4 h-full flex flex-col">
312312
<div className="px-2 md:px-0">
313313
<div className="h-10 bg-muted/50 animate-pulse rounded w-full" />
314314
</div>
315315
<div className="mx-2 md:mx-0 flex-1 min-h-0">
316-
<div className="h-full overflow-y-auto pt-4 pb-2 md:pb-0">
316+
<div className="h-full overflow-y-auto pt-4 pb-2 md:pb-4">
317317
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-2 gap-3 md:gap-4 w-full">
318318
{Array.from({ length: 6 }).map((_, i) => (
319319
<div key={i} className="md:pl-8">
@@ -388,7 +388,7 @@ export function RepoList() {
388388

389389
return (
390390
<>
391-
<div className="px-0 md:p-4 h-full flex flex-col">
391+
<div className="px-0 md:px-4 md:pt-4 h-full flex flex-col">
392392
<RepoListControls
393393
searchQuery={searchQuery}
394394
onSearchChange={setSearchQuery}
@@ -416,7 +416,7 @@ export function RepoList() {
416416
/>
417417

418418
<div className="mx-2 md:mx-0 flex-1 min-h-0">
419-
<div className="h-full overflow-y-auto pt-4 md:pb-0 [mask-image:linear-gradient(to_bottom,transparent,black_16px,black)]">
419+
<div className="h-full overflow-y-auto pt-4 md:pb-4 [mask-image:linear-gradient(to_bottom,transparent,black_16px,black)]">
420420
{(() => {
421421
switch (true) {
422422
case sortedViewModels.length === 0:

‎frontend/src/components/servers/RemoteProjectList.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function RemoteProjectListLoading() {
7474
<div className="h-10 bg-muted/50 animate-pulse rounded w-full" />
7575
</div>
7676
<div className="mx-2 md:mx-0 flex-1 min-h-0">
77-
<div className="h-full overflow-y-auto pt-4 pb-2 md:pb-0">
77+
<div className="h-full overflow-y-auto pt-4 pb-2 md:pb-4">
7878
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-2 gap-3 md:gap-4 w-full">
7979
{Array.from({ length: 6 }).map((_, index) => (
8080
<RepoCardSkeleton key={index} />
@@ -117,7 +117,7 @@ function RemoteProjectListContent({ serverId }: { serverId: string }) {
117117
const openSettings = () => openTab('servers')
118118

119119
return (
120-
<div className="flex h-full flex-col px-0 md:p-4">
120+
<div className="flex h-full flex-col px-0 md:px-4 md:pt-4">
121121
{!serversLoading && !server ? (
122122
<LinkedServerStateCard
123123
icon={Server}
@@ -181,7 +181,7 @@ function RemoteProjectListContent({ serverId }: { serverId: string }) {
181181
<OpenDirectoryTrigger onClick={() => setOpenDirectoryOpen(true)} />
182182
</div>
183183
<div className="mx-2 flex min-h-0 flex-1 md:mx-0">
184-
<div className="h-full w-full overflow-y-auto pt-4 md:pb-0 [mask-image:linear-gradient(to_bottom,transparent,black_16px,black)]">
184+
<div className="h-full w-full overflow-y-auto pt-4 md:pb-4 [mask-image:linear-gradient(to_bottom,transparent,black_16px,black)]">
185185
{filteredProjects.length === 0 ? (
186186
<div className="text-center p-12">
187187
<Search className="w-12 h-12 mx-auto mb-4 text-muted-foreground" />

‎frontend/src/components/session/FormPrompt.tsx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,10 +328,10 @@ export function FormPrompt({ form, onReply, onCancel, onMinimize, onAskSideQuest
328328

329329
return (
330330
<div
331-
className="flex flex-1 min-h-0 flex-col overflow-hidden rounded-t-[22px] border-t border-primary/40 bg-background bg-gradient-to-b from-primary/15 to-card mb-1 md:flex-none md:rounded-xl md:border-2 md:border-primary/40 md:bg-gradient-to-br md:from-primary/10 md:to-primary/20 md:shadow-lg md:shadow-primary/20"
331+
className="flex flex-1 min-h-0 flex-col overflow-hidden rounded-t-[22px] border-t border-primary/40 bg-background bg-gradient-to-b from-primary/15 to-card mb-1 md:flex-initial md:rounded-xl md:border-2 md:border-primary/40 md:bg-gradient-to-br md:from-primary/10 md:to-primary/20 md:shadow-lg md:shadow-primary/20"
332332
style={isMobile ? swipeStyles : undefined}
333333
>
334-
<div ref={mobileHeaderRef} className="shrink-0 md:hidden">
334+
<div ref={mobileHeaderRef} className="shrink-0 border-b border-primary/25 bg-primary/10 md:hidden">
335335
<button
336336
type="button"
337337
onClick={handleMinimize}
@@ -349,7 +349,7 @@ export function FormPrompt({ form, onReply, onCancel, onMinimize, onAskSideQuest
349349
>
350350
Dismiss
351351
</button>
352-
<span className="min-w-0 flex-1 truncate text-center text-[13px] font-semibold uppercase tracking-wide text-muted-foreground">
352+
<span className="min-w-0 flex-1 truncate text-center text-[13px] font-semibold uppercase tracking-wide text-primary">
353353
{form.title || 'Form'}
354354
</span>
355355
<button
@@ -387,7 +387,7 @@ export function FormPrompt({ form, onReply, onCancel, onMinimize, onAskSideQuest
387387
</div>
388388

389389
{!isMinimized && (
390-
<div className="flex-1 min-h-0 overflow-y-auto overflow-x-hidden overscroll-contain px-4 pt-2 pb-6 space-y-7 md:flex-none md:p-3 md:max-h-[70vh] md:space-y-3 md:bg-background/60 dark:md:bg-background/30">
390+
<div className="flex-1 min-h-0 overflow-y-auto overflow-x-hidden overscroll-contain px-4 pt-4 pb-6 space-y-7 bg-background/60 dark:bg-background/30 md:flex-initial md:p-3 md:max-h-[70vh] md:space-y-3">
391391
{renderFields.map((field) =>
392392
field.type === 'external' ? (
393393
<ExternalFieldCard key={field.key} field={field} />

‎frontend/src/pages/SessionDetail.tsx‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,8 @@ export function SessionDetail() {
331331
const { getForSession: getFormForSession, reply: replyToForm, cancel: cancelForm, syncForSession: syncFormsForSession } = useForms();
332332
const currentForm = sessionId ? getFormForSession(sessionId) : null;
333333
const minimizedForm = currentForm && currentForm.id === minimizedFormId ? currentForm : null;
334-
const isFormSheetOpen = isMobile && !!currentForm && !minimizedForm;
334+
const isFormOpen = !!currentForm && !minimizedForm;
335+
const isFormSheetOpen = isMobile && isFormOpen;
335336

336337
const lastAssistantMessage = messages.filter(m => m.type === 'assistant').at(-1);
337338
const lastAssistantText = getAssistantText(lastAssistantMessage);
@@ -876,18 +877,20 @@ export function SessionDetail() {
876877
</div>
877878
{sessionDirectory && !isEditingMessage && (
878879
<div
879-
ref={promptOverlayRef}
880880
data-testid="prompt-overlay"
881881
className={cn(
882882
"absolute left-0 right-0 flex justify-center",
883-
isFormSheetOpen && "top-0 flex-col items-center justify-start",
883+
isFormOpen && "top-0 flex-col items-center justify-end pointer-events-none md:pt-3",
884884
)}
885885
style={{ bottom: inputBottomOffset }}
886886
>
887887
<div
888+
ref={promptOverlayRef}
888889
className={cn(
889-
"relative",
890-
isFormSheetOpen ? "flex w-full flex-1 min-h-0 flex-col" : "w-[94%] md:max-w-4xl",
890+
"relative pointer-events-auto",
891+
isFormSheetOpen
892+
? "flex w-full flex-1 min-h-0 flex-col"
893+
: cn("w-[94%] md:max-w-4xl", isFormOpen && "flex max-h-full min-h-0 flex-col"),
891894
)}
892895
>
893896
{!isFormSheetOpen && (
@@ -945,7 +948,7 @@ export function SessionDetail() {
945948
onAskSideQuestion={() => handleAskSideQuestion('')}
946949
/>
947950
)}
948-
<div className={cn(isFormSheetOpen && "shrink-0 px-[3%]")}>
951+
<div className={cn(isFormSheetOpen && "shrink-0 bg-background px-[3%]")}>
949952
<SessionSendErrorBanner sessionId={sessionId} isConnected={streamConnected} isReconnecting={streamReconnecting} />
950953
<SessionGoalBar sessionID={sessionId} />
951954
<BackgroundWorkBar

‎frontend/src/pages/__tests__/SessionDetail.form-prompt.test.tsx‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,18 @@ describe('SessionDetail form prompt session scoping', () => {
369369
expect(screen.getByTestId('prompt-overlay')).toHaveClass('top-0')
370370
})
371371

372+
it('bounds the form card by the space above the prompt on desktop so its header stays visible', async () => {
373+
mocks.useMobile.mockReturnValue(false)
374+
formsState.bySession[VIEWED_SESSION_ID] = viewedSessionForm
375+
376+
render(renderTree())
377+
378+
await waitFor(() => expect(screen.getAllByText('Continue A')[0]).toBeInTheDocument())
379+
const overlay = screen.getByTestId('prompt-overlay')
380+
expect(overlay).toHaveClass('top-0', 'justify-end', 'pointer-events-none')
381+
expect(overlay.firstElementChild).toHaveClass('max-h-full', 'min-h-0', 'pointer-events-auto')
382+
})
383+
372384
it('keeps the prompt overlay anchored without an open form or once the form is minimized', async () => {
373385
mocks.useMobile.mockReturnValue(true)
374386

0 commit comments

Comments
 (0)