Skip to content

Commit 5420747

Browse files
authored
Merge pull request #3 from OpenKnots/okcode/thread-file-row-toggle
Make changed-file sections collapsible per turn
2 parents 4c5abbd + df7ab36 commit 5420747

1 file changed

Lines changed: 49 additions & 19 deletions

File tree

apps/web/src/components/chat/MessagesTimeline.tsx

Lines changed: 49 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import ChatMarkdown from "../ChatMarkdown";
2222
import {
2323
BotIcon,
2424
CheckIcon,
25+
ChevronRightIcon,
2526
CircleAlertIcon,
2627
EyeIcon,
2728
GlobeIcon,
@@ -303,6 +304,16 @@ export const MessagesTimeline = memo(function MessagesTimeline({
303304
}));
304305
}, []);
305306

307+
const [collapsedFileSectionsByTurnId, setCollapsedFileSectionsByTurnId] = useState<
308+
Record<string, boolean>
309+
>({});
310+
const onToggleFileSection = useCallback((turnId: TurnId) => {
311+
setCollapsedFileSectionsByTurnId((current) => ({
312+
...current,
313+
[turnId]: !(current[turnId] ?? false),
314+
}));
315+
}, []);
316+
306317
const renderRowContent = (row: TimelineRow) => (
307318
<div
308319
className="pb-4"
@@ -463,10 +474,23 @@ export const MessagesTimeline = memo(function MessagesTimeline({
463474
const changedFileCountLabel = String(checkpointFiles.length);
464475
const allDirectoriesExpanded =
465476
allDirectoriesExpandedByTurnId[turnSummary.turnId] ?? true;
477+
const isFileSectionCollapsed =
478+
collapsedFileSectionsByTurnId[turnSummary.turnId] ?? false;
466479
return (
467480
<div className="mt-2 rounded-lg border border-border/80 bg-card/45 p-2.5">
468-
<div className="mb-1.5 flex items-center justify-between gap-2">
469-
<p className="text-[10px] uppercase tracking-[0.12em] text-muted-foreground/65">
481+
<div className="flex items-center justify-between gap-2">
482+
<button
483+
type="button"
484+
className="group flex items-center gap-1.5 text-[10px] uppercase tracking-[0.12em] text-muted-foreground/65 hover:text-muted-foreground/90 transition-colors duration-150"
485+
onClick={() => onToggleFileSection(turnSummary.turnId)}
486+
>
487+
<ChevronRightIcon
488+
aria-hidden="true"
489+
className={cn(
490+
"size-3 shrink-0 transition-transform duration-150",
491+
!isFileSectionCollapsed && "rotate-90",
492+
)}
493+
/>
470494
<span>Changed files ({changedFileCountLabel})</span>
471495
{hasNonZeroStat(summaryStat) && (
472496
<>
@@ -477,16 +501,18 @@ export const MessagesTimeline = memo(function MessagesTimeline({
477501
/>
478502
</>
479503
)}
480-
</p>
504+
</button>
481505
<div className="flex items-center gap-1.5">
482-
<Button
483-
type="button"
484-
size="xs"
485-
variant="outline"
486-
onClick={() => onToggleAllDirectories(turnSummary.turnId)}
487-
>
488-
{allDirectoriesExpanded ? "Collapse all" : "Expand all"}
489-
</Button>
506+
{!isFileSectionCollapsed && (
507+
<Button
508+
type="button"
509+
size="xs"
510+
variant="outline"
511+
onClick={() => onToggleAllDirectories(turnSummary.turnId)}
512+
>
513+
{allDirectoriesExpanded ? "Collapse all" : "Expand all"}
514+
</Button>
515+
)}
490516
<Button
491517
type="button"
492518
size="xs"
@@ -499,14 +525,18 @@ export const MessagesTimeline = memo(function MessagesTimeline({
499525
</Button>
500526
</div>
501527
</div>
502-
<ChangedFilesTree
503-
key={`changed-files-tree:${turnSummary.turnId}`}
504-
turnId={turnSummary.turnId}
505-
files={checkpointFiles}
506-
allDirectoriesExpanded={allDirectoriesExpanded}
507-
resolvedTheme={resolvedTheme}
508-
onOpenTurnDiff={onOpenTurnDiff}
509-
/>
528+
{!isFileSectionCollapsed && (
529+
<div className="mt-1.5">
530+
<ChangedFilesTree
531+
key={`changed-files-tree:${turnSummary.turnId}`}
532+
turnId={turnSummary.turnId}
533+
files={checkpointFiles}
534+
allDirectoriesExpanded={allDirectoriesExpanded}
535+
resolvedTheme={resolvedTheme}
536+
onOpenTurnDiff={onOpenTurnDiff}
537+
/>
538+
</div>
539+
)}
510540
</div>
511541
);
512542
})()}

0 commit comments

Comments
 (0)