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:
committed by
GitHub
parent
c49a008c80
commit
49840a05c3
@@ -413,260 +413,269 @@ export function TaskFollowUpSection({
|
||||
selectedAttemptId && (
|
||||
<div
|
||||
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'
|
||||
)}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
{followUpError && (
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>{followUpError}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
{/* Scrollable content area */}
|
||||
<div className="overflow-y-auto min-h-0 p-4">
|
||||
<div className="space-y-2">
|
||||
<div
|
||||
className={cn(
|
||||
'mb-2',
|
||||
!showImageUpload && images.length === 0 && 'hidden'
|
||||
{followUpError && (
|
||||
<Alert variant="destructive">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>{followUpError}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<div className="space-y-2">
|
||||
<div
|
||||
className={cn(
|
||||
'mb-2',
|
||||
!showImageUpload && images.length === 0 && 'hidden'
|
||||
)}
|
||||
>
|
||||
<ImageUploadSection
|
||||
ref={imageUploadRef}
|
||||
images={images}
|
||||
onImagesChange={setImages}
|
||||
onUpload={(file) => imagesApi.uploadForTask(task.id, file)}
|
||||
onDelete={imagesApi.delete}
|
||||
onImageUploaded={(image) => {
|
||||
handleImageUploaded(image);
|
||||
setFollowUpMessage((prev) =>
|
||||
appendImageMarkdown(prev, image)
|
||||
);
|
||||
}}
|
||||
disabled={!isEditable}
|
||||
collapsible={false}
|
||||
defaultExpanded={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Review comments preview */}
|
||||
{reviewMarkdown && (
|
||||
<div className="mb-4">
|
||||
<div className="text-sm whitespace-pre-wrap break-words rounded-md border bg-muted p-3">
|
||||
{reviewMarkdown}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<ImageUploadSection
|
||||
ref={imageUploadRef}
|
||||
images={images}
|
||||
onImagesChange={setImages}
|
||||
onUpload={(file) => imagesApi.uploadForTask(task.id, file)}
|
||||
onDelete={imagesApi.delete}
|
||||
onImageUploaded={(image) => {
|
||||
handleImageUploaded(image);
|
||||
setFollowUpMessage((prev) =>
|
||||
appendImageMarkdown(prev, image)
|
||||
);
|
||||
}}
|
||||
|
||||
{/* Conflict notice and actions (optional UI) */}
|
||||
{branchStatus && (
|
||||
<FollowUpConflictSection
|
||||
selectedAttemptId={selectedAttemptId}
|
||||
attemptBranch={attemptBranch}
|
||||
branchStatus={branchStatus}
|
||||
isEditable={isEditable}
|
||||
onResolve={onSendFollowUp}
|
||||
enableResolve={
|
||||
canSendFollowUp && !isAttemptRunning && isEditable
|
||||
}
|
||||
enableAbort={canSendFollowUp && !isAttemptRunning}
|
||||
conflictResolutionInstructions={
|
||||
conflictResolutionInstructions
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Clicked elements notice and actions */}
|
||||
<ClickedElementsBanner />
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<FollowUpEditorCard
|
||||
placeholder={
|
||||
isQueued
|
||||
? 'Type your follow-up… It will auto-send when ready.'
|
||||
: reviewMarkdown || conflictResolutionInstructions
|
||||
? '(Optional) Add additional instructions... Type @ to insert tags or search files.'
|
||||
: 'Continue working on this task attempt... Type @ to insert tags or search files.'
|
||||
}
|
||||
value={followUpMessage}
|
||||
onChange={(value) => {
|
||||
setFollowUpMessage(value);
|
||||
if (followUpError) setFollowUpError(null);
|
||||
}}
|
||||
disabled={!isEditable}
|
||||
showLoadingOverlay={isUnqueuing || !isDraftLoaded}
|
||||
onPasteFiles={handlePasteImages}
|
||||
onFocusChange={setIsTextareaFocused}
|
||||
/>
|
||||
<FollowUpStatusRow
|
||||
status={{
|
||||
save: { state: saveStatus, isSaving },
|
||||
draft: {
|
||||
isLoaded: isDraftLoaded,
|
||||
isSending: !!draft?.sending,
|
||||
},
|
||||
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-1 flex gap-2">
|
||||
{/* Image button */}
|
||||
<Button
|
||||
variant={
|
||||
images.length > 0 || showImageUpload ? 'default' : 'secondary'
|
||||
}
|
||||
size="sm"
|
||||
onClick={() => setShowImageUpload(!showImageUpload)}
|
||||
disabled={!isEditable}
|
||||
>
|
||||
<ImageIcon className="h-4 w-4" />
|
||||
</Button>
|
||||
|
||||
<VariantSelector
|
||||
currentProfile={currentProfile}
|
||||
selectedVariant={selectedVariant}
|
||||
onChange={setSelectedVariant}
|
||||
disabled={!isEditable}
|
||||
collapsible={false}
|
||||
defaultExpanded={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Review comments preview */}
|
||||
{reviewMarkdown && (
|
||||
<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">
|
||||
{reviewMarkdown}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Conflict notice and actions (optional UI) */}
|
||||
{branchStatus && (
|
||||
<FollowUpConflictSection
|
||||
selectedAttemptId={selectedAttemptId}
|
||||
attemptBranch={attemptBranch}
|
||||
branchStatus={branchStatus}
|
||||
isEditable={isEditable}
|
||||
onResolve={onSendFollowUp}
|
||||
enableResolve={
|
||||
canSendFollowUp && !isAttemptRunning && isEditable
|
||||
}
|
||||
enableAbort={canSendFollowUp && !isAttemptRunning}
|
||||
conflictResolutionInstructions={conflictResolutionInstructions}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Clicked elements notice and actions */}
|
||||
<ClickedElementsBanner />
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
<FollowUpEditorCard
|
||||
placeholder={
|
||||
isQueued
|
||||
? 'Type your follow-up… It will auto-send when ready.'
|
||||
: reviewMarkdown || conflictResolutionInstructions
|
||||
? '(Optional) Add additional instructions... Type @ to insert tags or search files.'
|
||||
: 'Continue working on this task attempt... Type @ to insert tags or search files.'
|
||||
}
|
||||
value={followUpMessage}
|
||||
onChange={(value) => {
|
||||
setFollowUpMessage(value);
|
||||
if (followUpError) setFollowUpError(null);
|
||||
}}
|
||||
disabled={!isEditable}
|
||||
showLoadingOverlay={isUnqueuing || !isDraftLoaded}
|
||||
onPasteFiles={handlePasteImages}
|
||||
onFocusChange={setIsTextareaFocused}
|
||||
/>
|
||||
<FollowUpStatusRow
|
||||
status={{
|
||||
save: { state: saveStatus, isSaving },
|
||||
draft: {
|
||||
isLoaded: isDraftLoaded,
|
||||
isSending: !!draft?.sending,
|
||||
},
|
||||
queue: { isUnqueuing: isUnqueuing, isQueued: displayQueued },
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<div className="flex-1 flex gap-2">
|
||||
{/* Image button */}
|
||||
{isAttemptRunning ? (
|
||||
<Button
|
||||
onClick={stopExecution}
|
||||
disabled={isStopping}
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
>
|
||||
{isStopping ? (
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
) : (
|
||||
<>
|
||||
<StopCircle className="h-4 w-4 mr-2" />
|
||||
{t('followUp.stop')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
{comments.length > 0 && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => setShowImageUpload(!showImageUpload)}
|
||||
disabled={!isEditable}
|
||||
>
|
||||
<ImageIcon
|
||||
className={cn(
|
||||
'h-4 w-4',
|
||||
(images.length > 0 || showImageUpload) && 'text-primary'
|
||||
)}
|
||||
/>
|
||||
</Button>
|
||||
|
||||
<VariantSelector
|
||||
currentProfile={currentProfile}
|
||||
selectedVariant={selectedVariant}
|
||||
onChange={setSelectedVariant}
|
||||
disabled={!isEditable}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isAttemptRunning ? (
|
||||
<Button
|
||||
onClick={stopExecution}
|
||||
disabled={isStopping}
|
||||
onClick={clearComments}
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
disabled={!isEditable}
|
||||
>
|
||||
{isStopping ? (
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
) : (
|
||||
{t('followUp.clearReviewComments')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={onSendFollowUp}
|
||||
disabled={
|
||||
!canSendFollowUp ||
|
||||
isDraftLocked ||
|
||||
!isDraftLoaded ||
|
||||
isSendingFollowUp ||
|
||||
isRetryActive
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
{isSendingFollowUp ? (
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
) : (
|
||||
<>
|
||||
<Send className="h-4 w-4 mr-2" />
|
||||
{conflictResolutionInstructions
|
||||
? t('followUp.resolveConflicts')
|
||||
: t('followUp.send')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
{isQueued && (
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
className="min-w-[180px] transition-all"
|
||||
onClick={async () => {
|
||||
setIsUnqueuing(true);
|
||||
try {
|
||||
const ok = await onUnqueue();
|
||||
if (ok) setQueuedOptimistic(false);
|
||||
} finally {
|
||||
setIsUnqueuing(false);
|
||||
}
|
||||
}}
|
||||
disabled={isUnqueuing}
|
||||
>
|
||||
{isUnqueuing ? (
|
||||
<>
|
||||
<StopCircle className="h-4 w-4 mr-2" />
|
||||
{t('followUp.stop')}
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
{t('followUp.unqueuing')}
|
||||
</>
|
||||
) : (
|
||||
t('followUp.edit')
|
||||
)}
|
||||
</Button>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
{comments.length > 0 && (
|
||||
<Button
|
||||
onClick={clearComments}
|
||||
size="sm"
|
||||
variant="destructive"
|
||||
disabled={!isEditable}
|
||||
>
|
||||
{t('followUp.clearReviewComments')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={onSendFollowUp}
|
||||
disabled={
|
||||
!canSendFollowUp ||
|
||||
isDraftLocked ||
|
||||
!isDraftLoaded ||
|
||||
isSendingFollowUp ||
|
||||
isRetryActive
|
||||
}
|
||||
size="sm"
|
||||
>
|
||||
{isSendingFollowUp ? (
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
) : (
|
||||
<>
|
||||
<Send className="h-4 w-4 mr-2" />
|
||||
{conflictResolutionInstructions
|
||||
? t('followUp.resolveConflicts')
|
||||
: t('followUp.send')}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
{isQueued && (
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
className="min-w-[180px] transition-all"
|
||||
onClick={async () => {
|
||||
setIsUnqueuing(true);
|
||||
try {
|
||||
const ok = await onUnqueue();
|
||||
if (ok) setQueuedOptimistic(false);
|
||||
} finally {
|
||||
setIsUnqueuing(false);
|
||||
}
|
||||
}}
|
||||
disabled={isUnqueuing}
|
||||
>
|
||||
{isUnqueuing ? (
|
||||
<>
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
{t('followUp.unqueuing')}
|
||||
</>
|
||||
) : (
|
||||
t('followUp.edit')
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{isAttemptRunning && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
onClick={async () => {
|
||||
if (displayQueued) {
|
||||
setIsUnqueuing(true);
|
||||
try {
|
||||
const ok = await onUnqueue();
|
||||
if (ok) setQueuedOptimistic(false);
|
||||
} finally {
|
||||
setIsUnqueuing(false);
|
||||
}
|
||||
} else {
|
||||
setIsQueuing(true);
|
||||
try {
|
||||
const ok = await onQueue();
|
||||
if (ok) setQueuedOptimistic(true);
|
||||
} finally {
|
||||
setIsQueuing(false);
|
||||
}
|
||||
}
|
||||
}}
|
||||
disabled={
|
||||
displayQueued
|
||||
? isUnqueuing
|
||||
: !canSendFollowUp ||
|
||||
!isDraftLoaded ||
|
||||
isQueuing ||
|
||||
isUnqueuing ||
|
||||
!!draft?.sending ||
|
||||
isRetryActive
|
||||
}
|
||||
size="sm"
|
||||
variant="default"
|
||||
className="md:min-w-[180px] transition-all"
|
||||
>
|
||||
{displayQueued ? (
|
||||
isUnqueuing ? (
|
||||
<>
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
{t('followUp.unqueuing')}
|
||||
</>
|
||||
) : (
|
||||
t('followUp.edit')
|
||||
)
|
||||
) : isQueuing ? (
|
||||
<>
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
{t('followUp.queuing')}
|
||||
</>
|
||||
) : (
|
||||
t('followUp.queueForNextTurn')
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{isAttemptRunning && (
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
onClick={async () => {
|
||||
if (displayQueued) {
|
||||
setIsUnqueuing(true);
|
||||
try {
|
||||
const ok = await onUnqueue();
|
||||
if (ok) setQueuedOptimistic(false);
|
||||
} finally {
|
||||
setIsUnqueuing(false);
|
||||
}
|
||||
} else {
|
||||
setIsQueuing(true);
|
||||
try {
|
||||
const ok = await onQueue();
|
||||
if (ok) setQueuedOptimistic(true);
|
||||
} finally {
|
||||
setIsQueuing(false);
|
||||
}
|
||||
}
|
||||
}}
|
||||
disabled={
|
||||
displayQueued
|
||||
? isUnqueuing
|
||||
: !canSendFollowUp ||
|
||||
!isDraftLoaded ||
|
||||
isQueuing ||
|
||||
isUnqueuing ||
|
||||
!!draft?.sending ||
|
||||
isRetryActive
|
||||
}
|
||||
size="sm"
|
||||
variant="default"
|
||||
className="md:min-w-[180px] transition-all"
|
||||
>
|
||||
{displayQueued ? (
|
||||
isUnqueuing ? (
|
||||
<>
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
{t('followUp.unqueuing')}
|
||||
</>
|
||||
) : (
|
||||
t('followUp.edit')
|
||||
)
|
||||
) : isQueuing ? (
|
||||
<>
|
||||
<Loader2 className="animate-spin h-4 w-4 mr-2" />
|
||||
{t('followUp.queuing')}
|
||||
</>
|
||||
) : (
|
||||
t('followUp.queueForNextTurn')
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,7 +51,7 @@ export function FollowUpEditorCard({
|
||||
disabled={disabled}
|
||||
projectId={projectId}
|
||||
rows={1}
|
||||
maxRows={30}
|
||||
maxRows={80}
|
||||
onPasteFiles={onPasteFiles}
|
||||
/>
|
||||
{showLoadingOverlay && (
|
||||
|
||||
@@ -41,12 +41,12 @@ export function FullAttemptLogsPage() {
|
||||
>
|
||||
<TaskAttemptPanel attempt={attempt} task={task}>
|
||||
{({ 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="border-t shrink-0">
|
||||
<div className="mx-auto w-full max-w-[50rem]">
|
||||
<div className="min-h-0 max-h-[50%] border-t overflow-hidden">
|
||||
<div className="mx-auto w-full max-w-[50rem] h-full min-h-0">
|
||||
{followUp}
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,10 +59,10 @@ export function FullAttemptLogsPage() {
|
||||
) : (
|
||||
<TaskAttemptPanel attempt={attempt} task={task}>
|
||||
{({ 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="border-t shrink-0">
|
||||
<div className="mx-auto w-full max-w-[50rem]">
|
||||
<div className="min-h-0 max-h-[50%] border-t overflow-hidden">
|
||||
<div className="mx-auto w-full max-w-[50rem] h-full min-h-0">
|
||||
{followUp}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -958,16 +958,20 @@ export function ProjectTasks() {
|
||||
{({ logs, followUp }) => (
|
||||
<>
|
||||
<GitErrorBanner />
|
||||
<div className="flex-1 min-h-0 flex flex-col">{logs}</div>
|
||||
<div className="flex-1 min-h-0 flex flex-col">
|
||||
<div className="flex-1 min-h-0 flex flex-col">{logs}</div>
|
||||
|
||||
<div className="shrink-0 border-t">
|
||||
<div className="mx-auto w-full max-w-[50rem]">
|
||||
<TodoPanel />
|
||||
<div className="shrink-0 border-t">
|
||||
<div className="mx-auto w-full max-w-[50rem]">
|
||||
<TodoPanel />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="shrink-0 border-t">
|
||||
<div className="mx-auto w-full max-w-[50rem]">{followUp}</div>
|
||||
<div className="min-h-0 max-h-[50%] border-t overflow-hidden">
|
||||
<div className="mx-auto w-full max-w-[50rem] h-full min-h-0">
|
||||
{followUp}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user