From 49840a05c3d0f39ebd52a6a54652a22913734141 Mon Sep 17 00:00:00 2001 From: Louis Knight-Webb Date: Sat, 15 Nov 2025 12:19:06 +0000 Subject: [PATCH] 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 --- .../components/tasks/TaskFollowUpSection.tsx | 479 +++++++++--------- .../tasks/follow-up/FollowUpEditorCard.tsx | 2 +- frontend/src/pages/full-attempt-logs.tsx | 12 +- frontend/src/pages/project-tasks.tsx | 18 +- 4 files changed, 262 insertions(+), 249 deletions(-) diff --git a/frontend/src/components/tasks/TaskFollowUpSection.tsx b/frontend/src/components/tasks/TaskFollowUpSection.tsx index 1bf8ce51..67f61369 100644 --- a/frontend/src/components/tasks/TaskFollowUpSection.tsx +++ b/frontend/src/components/tasks/TaskFollowUpSection.tsx @@ -413,260 +413,269 @@ export function TaskFollowUpSection({ selectedAttemptId && (
-
- {followUpError && ( - - - {followUpError} - - )} + {/* Scrollable content area */} +
-
+ + {followUpError} + + )} +
+
+ imagesApi.uploadForTask(task.id, file)} + onDelete={imagesApi.delete} + onImageUploaded={(image) => { + handleImageUploaded(image); + setFollowUpMessage((prev) => + appendImageMarkdown(prev, image) + ); + }} + disabled={!isEditable} + collapsible={false} + defaultExpanded={true} + /> +
+ + {/* Review comments preview */} + {reviewMarkdown && ( +
+
+ {reviewMarkdown} +
+
)} - > - imagesApi.uploadForTask(task.id, file)} - onDelete={imagesApi.delete} - onImageUploaded={(image) => { - handleImageUploaded(image); - setFollowUpMessage((prev) => - appendImageMarkdown(prev, image) - ); - }} + + {/* Conflict notice and actions (optional UI) */} + {branchStatus && ( + + )} + + {/* Clicked elements notice and actions */} + + +
+ { + setFollowUpMessage(value); + if (followUpError) setFollowUpError(null); + }} + disabled={!isEditable} + showLoadingOverlay={isUnqueuing || !isDraftLoaded} + onPasteFiles={handlePasteImages} + onFocusChange={setIsTextareaFocused} + /> + +
+
+
+
+ + {/* Always-visible action bar */} +
+
+
+ {/* Image button */} + + +
- {/* Review comments preview */} - {reviewMarkdown && ( -
-
- {reviewMarkdown} -
-
- )} - - {/* Conflict notice and actions (optional UI) */} - {branchStatus && ( - - )} - - {/* Clicked elements notice and actions */} - - -
- { - setFollowUpMessage(value); - if (followUpError) setFollowUpError(null); - }} - disabled={!isEditable} - showLoadingOverlay={isUnqueuing || !isDraftLoaded} - onPasteFiles={handlePasteImages} - onFocusChange={setIsTextareaFocused} - /> - -
-
- {/* Image button */} + {isAttemptRunning ? ( + + ) : ( +
+ {comments.length > 0 && ( - - -
- - {isAttemptRunning ? ( - + )} + + {isQueued && ( + - ) : ( -
- {comments.length > 0 && ( - - )} - - {isQueued && ( - - )} -
- )} - {isAttemptRunning && ( -
- -
)}
-
+ )} + {isAttemptRunning && ( +
+ +
+ )}
diff --git a/frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx b/frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx index 444f20ac..80222187 100644 --- a/frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx +++ b/frontend/src/components/tasks/follow-up/FollowUpEditorCard.tsx @@ -51,7 +51,7 @@ export function FollowUpEditorCard({ disabled={disabled} projectId={projectId} rows={1} - maxRows={30} + maxRows={80} onPasteFiles={onPasteFiles} /> {showLoadingOverlay && ( diff --git a/frontend/src/pages/full-attempt-logs.tsx b/frontend/src/pages/full-attempt-logs.tsx index d5f36875..32970871 100644 --- a/frontend/src/pages/full-attempt-logs.tsx +++ b/frontend/src/pages/full-attempt-logs.tsx @@ -41,12 +41,12 @@ export function FullAttemptLogsPage() { > {({ logs, followUp }) => ( -
+
{logs}
-
-
+
+
{followUp}
@@ -59,10 +59,10 @@ export function FullAttemptLogsPage() { ) : ( {({ logs, followUp }) => ( -
+
{logs}
-
-
+
+
{followUp}
diff --git a/frontend/src/pages/project-tasks.tsx b/frontend/src/pages/project-tasks.tsx index b8664e42..dbcc387c 100644 --- a/frontend/src/pages/project-tasks.tsx +++ b/frontend/src/pages/project-tasks.tsx @@ -958,16 +958,20 @@ export function ProjectTasks() { {({ logs, followUp }) => ( <> -
{logs}
+
+
{logs}
-
-
- +
+
+ +
-
-
-
{followUp}
+
+
+ {followUp} +
+
)}