fix: animate tool paths in sorted chat mode

Adds animated reveals for file path tool descriptions
Keeps sorted mode tool animations working without extra chat gaps
Preserves file icons, truncation, and click behavior
This commit is contained in:
Bohdan Triapitsyn
2026-05-15 22:58:46 +03:00
parent 774fb4be66
commit 88fc8bff22
3 changed files with 29 additions and 12 deletions
@@ -700,6 +700,7 @@ const TurnBlock = React.memo(({
const isFirstAssistant = assistantIndex === 0;
const isLastAssistant = assistantIndex === visibleAssistantMessages.length - 1;
const isActivityOwner = Boolean(activityOwnerMessageId) && message.info.id === activityOwnerMessageId;
const hasAnchoredActivitySegment = visibleActivitySegments.some((segment) => segment.anchorMessageId === message.info.id);
const shouldAttachFullTurnContext = chatRenderMode === 'sorted'
? isAssistantMessage
: (isActivityOwner || isFirstAssistant || isLastAssistant);
@@ -722,7 +723,11 @@ const TurnBlock = React.memo(({
activityOwnerMessageId,
isFirstAssistantInTurn: isFirstAssistant,
isLastAssistantInTurn: isLastAssistant,
isWorking: isLastTurn && sessionIsWorking && message.info.id === streamingAssistantMessageId,
isWorking: isLastTurn && sessionIsWorking && (
chatRenderMode === 'sorted'
? hasAnchoredActivitySegment
: message.info.id === streamingAssistantMessageId
),
hasTools: turn.hasTools,
hasReasoning: turn.hasReasoning,
...(shouldAttachFullTurnContext ? {
@@ -777,6 +782,7 @@ const TurnBlock = React.memo(({
activeStreamingPhase,
visibleAssistantMessages,
visibleAssistantIds,
visibleActivitySegments,
activityOwnerMessageId,
shouldAnimateUserMessage,
onUserAnimationConsumed,
@@ -242,18 +242,19 @@ const getRelativePathFromDirectory = (filePath: string, currentDirectory: string
return normalizedPath;
};
const renderReadFilePath = (displayPath: string) => {
const renderReadFilePath = (displayPath: string, animate = true) => {
const lastSlash = displayPath.lastIndexOf('/');
if (lastSlash === -1) {
return (
<span
<Text
variant={animate ? 'generate-effect' : 'static'}
className="min-w-0 flex-1 truncate whitespace-nowrap typography-meta leading-5"
style={{ color: 'var(--tools-title)' }}
title={displayPath}
>
{displayPath}
</span>
</Text>
);
}
@@ -277,7 +278,13 @@ const renderReadFilePath = (displayPath: string) => {
{displayDir}
</span>
<span className="flex-shrink-0" style={{ color: 'var(--tools-description)' }}>/</span>
<span className="flex-shrink-0" style={{ color: 'var(--tools-title)' }}>{name}</span>
<Text
variant={animate ? 'generate-effect' : 'static'}
className="flex-shrink-0"
style={{ color: 'var(--tools-title)' }}
>
{name}
</Text>
</span>
);
};
@@ -682,7 +689,7 @@ const StaticToolRowInner: React.FC<{
title={entry.offset ? `${entry.displayPath}:${entry.offset}` : entry.displayPath}
>
{showToolFileIcons ? <FileTypeIcon filePath={entry.path} className="h-3.5 w-3.5" /> : null}
{renderReadFilePath(entry.displayPath)}
{renderReadFilePath(entry.displayPath, animateTailText)}
</button>
))
: null}
@@ -1359,20 +1359,20 @@ const renderPathLikeGitChanges = (path: string, grow = true) => {
);
};
const renderAnimatedPathWithIcon = (path: string, _animate = true, grow = true, showFileIcons = true) => {
void _animate;
const renderAnimatedPathWithIcon = (path: string, animate = true, grow = true, showFileIcons = true) => {
const lastSlash = path.lastIndexOf('/');
if (lastSlash === -1) {
return (
<span className={cn('min-w-0 inline-flex items-center gap-1 overflow-hidden', grow && 'flex-1')} title={path}>
{showFileIcons ? <FileTypeIcon filePath={path} className="h-3.5 w-3.5 flex-shrink-0" /> : null}
<span
<Text
variant={animate ? 'generate-effect' : 'static'}
className={cn('min-w-0 truncate whitespace-nowrap typography-meta', grow && 'flex-1')}
style={{ color: 'var(--tools-title)' }}
>
{path}
</span>
</Text>
</span>
);
}
@@ -1399,9 +1399,13 @@ const renderAnimatedPathWithIcon = (path: string, _animate = true, grow = true,
{displayDir}
</span>
<span className="flex-shrink-0" style={{ color: 'var(--tools-description)' }}>/</span>
<span className="flex-shrink-0" style={{ color: 'var(--tools-title)' }}>
<Text
variant={animate ? 'generate-effect' : 'static'}
className="flex-shrink-0"
style={{ color: 'var(--tools-title)' }}
>
{name}
</span>
</Text>
</span>
</span>
);