From f14fa1b307810c1dbfb7dd44d71d509ab4c02402 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Mon, 25 May 2026 01:38:19 +0300 Subject: [PATCH] style: unify chat tool row spacing --- .../chat/message/parts/ProgressiveGroup.tsx | 22 ++++++++++------- .../chat/message/parts/ReasoningPart.tsx | 18 ++++++++------ .../chat/message/parts/ToolPart.tsx | 24 +++++++++++-------- .../ui/src/components/icons/FileTypeIcon.tsx | 2 +- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/packages/ui/src/components/chat/message/parts/ProgressiveGroup.tsx b/packages/ui/src/components/chat/message/parts/ProgressiveGroup.tsx index 2baf3608..01949045 100644 --- a/packages/ui/src/components/chat/message/parts/ProgressiveGroup.tsx +++ b/packages/ui/src/components/chat/message/parts/ProgressiveGroup.tsx @@ -24,6 +24,10 @@ import JustificationBlock from './JustificationBlock'; import { areRenderRelevantPartsEqual } from '../renderCompare'; import { getExternalFaviconUrl } from '@/lib/url'; +const TOOL_ROW_TEXT_CLASS = '!text-[length:var(--text-meta)] !leading-4 sm:!leading-6 tracking-normal'; +const TOOL_ROW_TITLE_CLASS = cn('typography-meta font-medium', TOOL_ROW_TEXT_CLASS); +const TOOL_ROW_DESCRIPTION_CLASS = cn('typography-meta', TOOL_ROW_TEXT_CLASS); + interface ProgressiveGroupProps { parts: TurnActivityPart[]; isExpanded: boolean; @@ -282,7 +286,7 @@ const renderReadFilePath = (displayPath: string, animate = true) => { return ( @@ -297,7 +301,7 @@ const renderReadFilePath = (displayPath: string, animate = true) => { const displayDir = hasAbsoluteRoot ? dir.slice(1) : dir; return ( - + {hasAbsoluteRoot ? / : null} @@ -755,7 +759,7 @@ const StaticToolRowInner: React.FC<{ event.stopPropagation(); handleReadFileClick(entry.path, entry.offset); }} - className="inline-flex items-center justify-start gap-1 min-w-0 flex-1 text-left typography-meta leading-5 hover:opacity-90" + className={cn('inline-flex !min-h-0 items-center justify-start gap-1 min-w-0 flex-1 text-left hover:opacity-90', TOOL_ROW_DESCRIPTION_CLASS)} style={{ color: 'var(--tools-description)' }} title={entry.offset ? `${entry.displayPath}:${entry.offset}` : entry.displayPath} > @@ -769,7 +773,7 @@ const StaticToolRowInner: React.FC<{ @@ -787,7 +791,7 @@ const StaticToolRowInner: React.FC<{ rel="noopener noreferrer" className={cn( 'min-w-0 flex-1 inline-flex items-center gap-1.5 underline decoration-[color:var(--status-info)] underline-offset-2 hover:opacity-90', - 'truncate whitespace-nowrap typography-meta' + 'truncate whitespace-nowrap', TOOL_ROW_DESCRIPTION_CLASS )} style={{ color: 'var(--status-info)' }} title={url} @@ -807,7 +811,7 @@ const StaticToolRowInner: React.FC<{ event.stopPropagation(); handleSkillClick(entry.path); }} - className="min-w-0 flex-1 truncate whitespace-nowrap typography-meta leading-5 text-left hover:opacity-90" + className={cn('!min-h-0 min-w-0 flex-1 truncate whitespace-nowrap text-left hover:opacity-90', TOOL_ROW_DESCRIPTION_CLASS)} style={{ color: 'var(--tools-description)' }} title={entry.path} > @@ -818,7 +822,7 @@ const StaticToolRowInner: React.FC<{ {!isReadGroup && !isSearchGroup && !isFetchGroup && !isSkillGroup && descriptions.length > 0 ? ( {descriptions.join(' ')} @@ -1050,7 +1054,7 @@ const ProgressiveGroup: React.FC = ({ diff --git a/packages/ui/src/components/chat/message/parts/ReasoningPart.tsx b/packages/ui/src/components/chat/message/parts/ReasoningPart.tsx index 51f7cefc..367d74a2 100644 --- a/packages/ui/src/components/chat/message/parts/ReasoningPart.tsx +++ b/packages/ui/src/components/chat/message/parts/ReasoningPart.tsx @@ -12,6 +12,10 @@ import { MarkdownRenderer } from '../../MarkdownRenderer'; import { useStreamingTextThrottle } from '../../hooks/useStreamingTextThrottle'; import type { StreamPhase } from '../types'; +const TOOL_ROW_TEXT_CLASS = '!text-[length:var(--text-meta)] !leading-4 sm:!leading-6 tracking-normal'; +const TOOL_ROW_TITLE_CLASS = cn('typography-meta font-medium', TOOL_ROW_TEXT_CLASS); +const TOOL_ROW_DESCRIPTION_CLASS = cn('typography-meta', TOOL_ROW_TEXT_CLASS); + type PartWithText = Part & { text?: string; content?: string; time?: { start?: number; end?: number } }; export type ReasoningVariant = 'thinking' | 'justification'; @@ -217,7 +221,7 @@ export const ReasoningTimelineBlock: React.FC = ({ // Short blocks: render content directly without a collapsible toggle. if (isShort) { return ( -
+
= ({ } return ( -
+
= ({
{isStreaming ? ( - + {t(variant === 'justification' ? 'chat.reasoningTrace.justification' : 'chat.reasoningTrace.thinking')} ) : isExpanded ? ( {t(variant === 'justification' ? 'chat.reasoningTrace.justification' : 'chat.reasoningTrace.thinking')} ) : ( {t(variant === 'justification' ? 'chat.reasoningTrace.justification' : 'chat.reasoningTrace.thinking')} @@ -298,10 +302,10 @@ export const ReasoningTimelineBlock: React.FC = ({ )}
-
+
{!isStreaming && !isExpanded && summary ? ( diff --git a/packages/ui/src/components/chat/message/parts/ToolPart.tsx b/packages/ui/src/components/chat/message/parts/ToolPart.tsx index 9ffc5fec..5957b171 100644 --- a/packages/ui/src/components/chat/message/parts/ToolPart.tsx +++ b/packages/ui/src/components/chat/message/parts/ToolPart.tsx @@ -45,6 +45,10 @@ import { resolveFallbackTaskSessionId } from './resolveFallbackTaskSessionId'; import { areRenderRelevantPartsEqual } from '../renderCompare'; import { useI18n } from '@/lib/i18n'; +const TOOL_ROW_TEXT_CLASS = '!text-[length:var(--text-meta)] !leading-4 sm:!leading-6 tracking-normal'; +const TOOL_ROW_TITLE_CLASS = cn('typography-meta font-medium', TOOL_ROW_TEXT_CLASS); +const TOOL_ROW_DESCRIPTION_CLASS = cn('typography-meta', TOOL_ROW_TEXT_CLASS); + type ToolStateWithMetadata = ToolStateUnion & { metadata?: Record; input?: Record; output?: string; error?: string; time?: { start: number; end?: number } }; interface ToolPartProps { @@ -113,11 +117,11 @@ const getMultiFileDescription = ( {entries.map((entry) => { const hasPerFileDiff = entry.added !== null || entry.removed !== null; return ( - + {showFileIcons ? : null} @@ -1400,7 +1404,7 @@ const renderAnimatedPathWithIcon = (path: string, animate = true, grow = true, s {showFileIcons ? : null} {path} @@ -1417,7 +1421,7 @@ const renderAnimatedPathWithIcon = (path: string, animate = true, grow = true, s return ( {showFileIcons ? : null} - + {hasAbsoluteRoot ? / : null} = ({ @@ -2716,7 +2720,7 @@ const ToolPart: React.FC = ({ @@ -2724,7 +2728,7 @@ const ToolPart: React.FC = ({
{normalizedPartTool === 'bash' && typeof effectiveTimeStart === 'number' ? ( - + = ({
{!isMultiFileApplyPatch && ( -
+
{justificationText && ( @@ -2754,7 +2758,7 @@ const ToolPart: React.FC = ({ ) : ( diff --git a/packages/ui/src/components/icons/FileTypeIcon.tsx b/packages/ui/src/components/icons/FileTypeIcon.tsx index 5acca7a3..b23a471c 100644 --- a/packages/ui/src/components/icons/FileTypeIcon.tsx +++ b/packages/ui/src/components/icons/FileTypeIcon.tsx @@ -16,7 +16,7 @@ export const FileTypeIcon: React.FC = ({ filePath, extension, return (