Follow up area text scroll (vibe-kanban) (#1295)

* Done! The textarea now has a maximum height of 40% of the viewport and will scroll internally, keeping the Send and other action buttons always visible on screen.

* Done! I've restructured [TaskFollowUpSection.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/components/tasks/TaskFollowUpSection.tsx) using a CSS Grid layout:

**Changes:**
- Root container is now a grid with `grid-rows-[minmax(0,1fr)_auto]`
- **Scrollable content area** (row 1): Contains all content - images, review comments, conflicts, textarea, status row
- **Fixed action bar** (row 2): Contains the image button, variant selector, and all action buttons (Stop/Send/Queue)

**Result:**
The action buttons are now **always visible** at the bottom, regardless of how much content is above or screen size. The content area scrolls independently when it exceeds available space.

* Cleanup script changes for task attempt ccffbb1b-ff71-424d-9bea-44081e584026

* Done! I've fixed the parent containers in all three locations:

**Updated files:**
1. [frontend/src/pages/project-tasks.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/project-tasks.tsx#L969-L971)
2. [frontend/src/pages/full-attempt-logs.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/full-attempt-logs.tsx#L48-L52) (first occurrence)
3. [frontend/src/pages/full-attempt-logs.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/full-attempt-logs.tsx#L64-L68) (second occurrence)

**What changed:**
- Replaced `shrink-0` with `min-h-0 overflow-hidden` on the outer wrapper
- Added `h-full min-h-0` to the inner max-width wrapper

**Result:**
The follow-up section can now shrink within the flex layout, giving TaskFollowUpSection's grid a real height constraint. The scrollable content area will scroll when multiple sections expand, while the action buttons remain always visible at the bottom.

* Cleanup script changes for task attempt ccffbb1b-ff71-424d-9bea-44081e584026

* Done! I've implemented the 50/50 maximum split across all layouts:

**Updated files:**
1. [frontend/src/pages/project-tasks.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/project-tasks.tsx#L961) - 3-row grid: logs (1fr) + TodoPanel (auto) + follow-up (1fr)
2. [frontend/src/pages/full-attempt-logs.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/full-attempt-logs.tsx#L43) - 2-row grid: logs (1fr) + follow-up (1fr)
3. [frontend/src/pages/full-attempt-logs.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/full-attempt-logs.tsx#L61) - 2-row grid: logs (1fr) + follow-up (1fr)

**Result:**
- Logs always get at least 50% of available vertical space
- Follow-up area capped at maximum 50%
- Action buttons remain always visible within the follow-up area
- Clean grid layout that clearly expresses the 50/50 constraint

* Cleanup script changes for task attempt ccffbb1b-ff71-424d-9bea-44081e584026

* Done! I've converted all layouts from grid to flex:

**Updated files:**
1. [frontend/src/pages/project-tasks.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/project-tasks.tsx#L961) - flex layout with `max-h-[50%]` cap
2. [frontend/src/pages/full-attempt-logs.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/full-attempt-logs.tsx#L44) - flex layout (first occurrence)
3. [frontend/src/pages/full-attempt-logs.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/pages/full-attempt-logs.tsx#L59) - flex layout (second occurrence)

**Result:**
- Logs use `flex-1` - fill remaining space
- TodoPanel uses `shrink-0` - natural size
- Follow-up uses `max-h-[50%]` - natural size up to 50% max
- Action buttons remain always visible
- Much clearer, more readable code that directly expresses the intent

* Cleanup script changes for task attempt ccffbb1b-ff71-424d-9bea-44081e584026

* Done! I've eliminated all nested scrolling:

**Changes made:**

1. [TaskFollowUpSection.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/components/tasks/TaskFollowUpSection.tsx#L497) - Removed `textareaClassName="max-h-[40vh] overflow-y-auto"` from textarea
2. [TaskFollowUpSection.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/components/tasks/TaskFollowUpSection.tsx#L456) - Removed `max-h-[40vh] overflow-y-auto` from review preview
3. [FollowUpEditorCard.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx#L53) - Increased `maxRows` from 30 to 80

**Result:**
- Single scroll container - only the follow-up content area scrolls
- Textarea auto-grows naturally up to 80 rows
- Review preview expands fully
- Action buttons remain fixed at bottom
- Clean, intuitive UX with no nested scrollbars

* Fixed! The issue was that the icon was using `text-primary` color on a `secondary` variant button, which can have poor contrast.

**Change made:**
[TaskFollowUpSection.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/ccff-follow-up-area-t/frontend/src/components/tasks/TaskFollowUpSection.tsx#L526) - Changed button variant to `default` when active (images present or upload area shown) and `secondary` when inactive, removing the custom icon color class.

**Result:**
The icon is now always clearly visible - the button changes its entire variant style when toggled, providing better visual feedback and contrast.

* Cleanup script changes for task attempt ccffbb1b-ff71-424d-9bea-44081e584026
This commit is contained in:
Louis Knight-Webb
2025-11-15 12:19:06 +00:00
committed by GitHub
parent c49a008c80
commit 49840a05c3
4 changed files with 262 additions and 249 deletions

View File

@@ -413,10 +413,12 @@ export function TaskFollowUpSection({
selectedAttemptId && ( selectedAttemptId && (
<div <div
className={cn( className={cn(
'p-4 focus-within:ring ring-inset', 'grid h-full min-h-0 grid-rows-[minmax(0,1fr)_auto] overflow-hidden focus-within:ring ring-inset',
isRetryActive && 'opacity-50' isRetryActive && 'opacity-50'
)} )}
> >
{/* Scrollable content area */}
<div className="overflow-y-auto min-h-0 p-4">
<div className="space-y-2"> <div className="space-y-2">
{followUpError && ( {followUpError && (
<Alert variant="destructive"> <Alert variant="destructive">
@@ -452,7 +454,7 @@ export function TaskFollowUpSection({
{/* Review comments preview */} {/* Review comments preview */}
{reviewMarkdown && ( {reviewMarkdown && (
<div className="mb-4"> <div className="mb-4">
<div className="text-sm whitespace-pre-wrap break-words max-h-[40vh] overflow-y-auto rounded-md border bg-muted p-3"> <div className="text-sm whitespace-pre-wrap break-words rounded-md border bg-muted p-3">
{reviewMarkdown} {reviewMarkdown}
</div> </div>
</div> </div>
@@ -470,7 +472,9 @@ export function TaskFollowUpSection({
canSendFollowUp && !isAttemptRunning && isEditable canSendFollowUp && !isAttemptRunning && isEditable
} }
enableAbort={canSendFollowUp && !isAttemptRunning} enableAbort={canSendFollowUp && !isAttemptRunning}
conflictResolutionInstructions={conflictResolutionInstructions} conflictResolutionInstructions={
conflictResolutionInstructions
}
/> />
)} )}
@@ -503,24 +507,31 @@ export function TaskFollowUpSection({
isLoaded: isDraftLoaded, isLoaded: isDraftLoaded,
isSending: !!draft?.sending, isSending: !!draft?.sending,
}, },
queue: { isUnqueuing: isUnqueuing, isQueued: displayQueued }, queue: {
isUnqueuing: isUnqueuing,
isQueued: displayQueued,
},
}} }}
/> />
</div>
</div>
</div>
</div>
{/* Always-visible action bar */}
<div className="border-t bg-background p-4">
<div className="flex flex-row gap-2 items-center"> <div className="flex flex-row gap-2 items-center">
<div className="flex-1 flex gap-2"> <div className="flex-1 flex gap-2">
{/* Image button */} {/* Image button */}
<Button <Button
variant="secondary" variant={
images.length > 0 || showImageUpload ? 'default' : 'secondary'
}
size="sm" size="sm"
onClick={() => setShowImageUpload(!showImageUpload)} onClick={() => setShowImageUpload(!showImageUpload)}
disabled={!isEditable} disabled={!isEditable}
> >
<ImageIcon <ImageIcon className="h-4 w-4" />
className={cn(
'h-4 w-4',
(images.length > 0 || showImageUpload) && 'text-primary'
)}
/>
</Button> </Button>
<VariantSelector <VariantSelector
@@ -668,8 +679,6 @@ export function TaskFollowUpSection({
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
) )
); );
} }

View File

@@ -51,7 +51,7 @@ export function FollowUpEditorCard({
disabled={disabled} disabled={disabled}
projectId={projectId} projectId={projectId}
rows={1} rows={1}
maxRows={30} maxRows={80}
onPasteFiles={onPasteFiles} onPasteFiles={onPasteFiles}
/> />
{showLoadingOverlay && ( {showLoadingOverlay && (

View File

@@ -41,12 +41,12 @@ export function FullAttemptLogsPage() {
> >
<TaskAttemptPanel attempt={attempt} task={task}> <TaskAttemptPanel attempt={attempt} task={task}>
{({ logs, followUp }) => ( {({ logs, followUp }) => (
<div className="h-full flex flex-col"> <div className="h-full min-h-0 flex flex-col">
<div className="flex-1 min-h-0 flex flex-col"> <div className="flex-1 min-h-0 flex flex-col">
{logs} {logs}
</div> </div>
<div className="border-t shrink-0"> <div className="min-h-0 max-h-[50%] border-t overflow-hidden">
<div className="mx-auto w-full max-w-[50rem]"> <div className="mx-auto w-full max-w-[50rem] h-full min-h-0">
{followUp} {followUp}
</div> </div>
</div> </div>
@@ -59,10 +59,10 @@ export function FullAttemptLogsPage() {
) : ( ) : (
<TaskAttemptPanel attempt={attempt} task={task}> <TaskAttemptPanel attempt={attempt} task={task}>
{({ logs, followUp }) => ( {({ logs, followUp }) => (
<div className="h-full flex flex-col"> <div className="h-full min-h-0 flex flex-col">
<div className="flex-1 min-h-0 flex flex-col">{logs}</div> <div className="flex-1 min-h-0 flex flex-col">{logs}</div>
<div className="border-t shrink-0"> <div className="min-h-0 max-h-[50%] border-t overflow-hidden">
<div className="mx-auto w-full max-w-[50rem]"> <div className="mx-auto w-full max-w-[50rem] h-full min-h-0">
{followUp} {followUp}
</div> </div>
</div> </div>

View File

@@ -958,6 +958,7 @@ export function ProjectTasks() {
{({ logs, followUp }) => ( {({ logs, followUp }) => (
<> <>
<GitErrorBanner /> <GitErrorBanner />
<div className="flex-1 min-h-0 flex flex-col">
<div className="flex-1 min-h-0 flex flex-col">{logs}</div> <div className="flex-1 min-h-0 flex flex-col">{logs}</div>
<div className="shrink-0 border-t"> <div className="shrink-0 border-t">
@@ -966,8 +967,11 @@ export function ProjectTasks() {
</div> </div>
</div> </div>
<div className="shrink-0 border-t"> <div className="min-h-0 max-h-[50%] border-t overflow-hidden">
<div className="mx-auto w-full max-w-[50rem]">{followUp}</div> <div className="mx-auto w-full max-w-[50rem] h-full min-h-0">
{followUp}
</div>
</div>
</div> </div>
</> </>
)} )}