diff --git a/src/renderer/src/components/right-sidebar/ChecksPanel.tsx b/src/renderer/src/components/right-sidebar/ChecksPanel.tsx
index 9eb7cef2e..9f54c3c84 100644
--- a/src/renderer/src/components/right-sidebar/ChecksPanel.tsx
+++ b/src/renderer/src/components/right-sidebar/ChecksPanel.tsx
@@ -145,6 +145,7 @@ import { localizedHostedReviewCopy } from '@/i18n/hosted-review-localized-copy'
import { translate } from '@/i18n/i18n'
import { groupPRComments, type PRCommentGroup } from '@/lib/pr-comment-groups'
import { openChecksPanelHostedReviewUrl } from './checks-panel-hosted-review-click-routing'
+import { ChecksPanelUpdatedAtMetadata } from './checks-panel-updated-at-metadata'
import {
clearPullRequestGenerationRequiresPushBeforeCreate,
createRunningPullRequestGenerationRecord,
@@ -3469,11 +3470,10 @@ export default function ChecksPanel(): React.JSX.Element {
{/* Updated at */}
{activeReview.updatedAt && (
-
- {reviewShortLabel}{' '}
- {translate('auto.components.right.sidebar.ChecksPanel.34464d00b9', 'updated')}
- {new Date(activeReview.updatedAt).toLocaleString()}
-
+
)}
{/* Merge / Delete Workspace actions */}
{activeReview && activeWorktree && repo && (
diff --git a/src/renderer/src/components/right-sidebar/ChecksPanel.updated-at-metadata.test.tsx b/src/renderer/src/components/right-sidebar/ChecksPanel.updated-at-metadata.test.tsx
new file mode 100644
index 000000000..48e9dc210
--- /dev/null
+++ b/src/renderer/src/components/right-sidebar/ChecksPanel.updated-at-metadata.test.tsx
@@ -0,0 +1,28 @@
+// @vitest-environment happy-dom
+
+import { renderToStaticMarkup } from 'react-dom/server'
+import { describe, expect, it } from 'vitest'
+import { ChecksPanelUpdatedAtMetadata } from './checks-panel-updated-at-metadata'
+
+function renderMetadataText(reviewShortLabel: string): string {
+ const container = document.createElement('div')
+ container.innerHTML = renderToStaticMarkup(
+
+ )
+ return container.textContent ?? ''
+}
+
+describe('ChecksPanel updated-at metadata', () => {
+ it.each(['PR', 'MR'])(
+ 'renders a whitespace boundary between the %s updated label and timestamp',
+ (reviewShortLabel) => {
+ const text = renderMetadataText(reviewShortLabel)
+
+ expect(text).toMatch(new RegExp(`${reviewShortLabel} updated\\s+\\S`))
+ expect(text).not.toMatch(new RegExp(`${reviewShortLabel} updated\\S`))
+ }
+ )
+})
diff --git a/src/renderer/src/components/right-sidebar/checks-panel-content.test.tsx b/src/renderer/src/components/right-sidebar/checks-panel-content.test.tsx
index 5ad62f79f..c3fa3ffd2 100644
--- a/src/renderer/src/components/right-sidebar/checks-panel-content.test.tsx
+++ b/src/renderer/src/components/right-sidebar/checks-panel-content.test.tsx
@@ -273,6 +273,9 @@ describe('PRCommentsList', () => {
expect(markup.indexOf('aria-label="Add comment"')).toBeLessThan(
markup.indexOf('Existing review context')
)
+ expect(markup.indexOf('aria-label="Comment display options"')).toBeLessThan(
+ markup.indexOf('aria-label="Add comment"')
+ )
expect(markup).toContain('lucide-plus')
expect(markup).not.toContain('Add a comment...')
expect(markup).not.toContain('Add a PR comment')
diff --git a/src/renderer/src/components/right-sidebar/checks-panel-content.tsx b/src/renderer/src/components/right-sidebar/checks-panel-content.tsx
index b3dc98cc7..988856a82 100644
--- a/src/renderer/src/components/right-sidebar/checks-panel-content.tsx
+++ b/src/renderer/src/components/right-sidebar/checks-panel-content.tsx
@@ -2461,6 +2461,42 @@ export function PRCommentsList({
)}
>
)}
+ {comments.length > 0 && (
+
+
+
+
+
+
+ {translate(
+ 'auto.components.right.sidebar.checks.panel.content.5e6e5a13fa',
+ 'View'
+ )}
+
+ setDisplayMode(value as PRCommentsListDisplayMode)}
+ >
+ {PR_COMMENT_LIST_DISPLAY_MODES.map((mode) => (
+
+ {getPRCommentsListDisplayModeLabel(mode)}
+
+ ))}
+
+
+
+ )}
{onAddComment && !isAddingComment && (
@@ -2502,42 +2538,6 @@ export function PRCommentsList({
)}
- {comments.length > 0 && (
-
-
-
-
-
-
- {translate(
- 'auto.components.right.sidebar.checks.panel.content.5e6e5a13fa',
- 'View'
- )}
-
- setDisplayMode(value as PRCommentsListDisplayMode)}
- >
- {PR_COMMENT_LIST_DISPLAY_MODES.map((mode) => (
-
- {getPRCommentsListDisplayModeLabel(mode)}
-
- ))}
-
-
-
- )}
{comments.length > 0 && (
diff --git a/src/renderer/src/components/right-sidebar/checks-panel-updated-at-metadata.tsx b/src/renderer/src/components/right-sidebar/checks-panel-updated-at-metadata.tsx
new file mode 100644
index 000000000..4c4a90b7e
--- /dev/null
+++ b/src/renderer/src/components/right-sidebar/checks-panel-updated-at-metadata.tsx
@@ -0,0 +1,20 @@
+import type React from 'react'
+import { translate } from '@/i18n/i18n'
+
+type ChecksPanelUpdatedAtMetadataProps = {
+ reviewShortLabel: string
+ updatedAt: string
+}
+
+export function ChecksPanelUpdatedAtMetadata({
+ reviewShortLabel,
+ updatedAt
+}: ChecksPanelUpdatedAtMetadataProps): React.JSX.Element {
+ return (
+
+ {reviewShortLabel}{' '}
+ {translate('auto.components.right.sidebar.ChecksPanel.34464d00b9', 'updated')}{' '}
+ {new Date(updatedAt).toLocaleString()}
+
+ )
+}
diff --git a/src/renderer/src/components/right-sidebar/pr-comment-presentation.test.ts b/src/renderer/src/components/right-sidebar/pr-comment-presentation.test.ts
index cfee6f48d..b85c7085d 100644
--- a/src/renderer/src/components/right-sidebar/pr-comment-presentation.test.ts
+++ b/src/renderer/src/components/right-sidebar/pr-comment-presentation.test.ts
@@ -15,15 +15,28 @@ describe('pr-comment-presentation', () => {
it('returns card layout tokens for cards and focus variants', () => {
const cards = getPRCommentPresentationClasses('cards')
expect(cards.useCardLayout).toBe(true)
- expect(cards.commentBody).toContain('text-[13px]')
+ expect(cards.commentBody).toContain('text-xs')
+ expect(cards.commentBody).toContain('leading-5')
expect(cards.commentBody).toContain('text-foreground')
expect(cards.group).toContain('bg-secondary')
expect(cards.group).toContain('shadow-xs')
expect(cards.avatar).toContain('border-border')
expect(cards.avatar).toContain('bg-background')
- expect(getPRCommentPresentationClasses('focus').useCardLayout).toBe(true)
- expect(getPRCommentPresentationClasses('focus').commentBody).toContain('text-[14px]')
+ const focus = getPRCommentPresentationClasses('focus')
+ expect(focus.useCardLayout).toBe(true)
+ expect(focus.commentBody).toContain('text-xs')
+ expect(focus.commentBody).toContain('leading-5')
+ expect(focus.commentBodyReply).toContain('text-xs')
+ expect(focus.commentBodyReply).toContain('leading-5')
+ expect(focus.author).toContain('text-[13px]')
+ expect(focus.list).toContain('gap-2')
+ expect(focus.commentBody).toContain('px-4 py-2.5')
+ expect(focus.commentBodyReply).toContain('px-4 py-2.5')
+ expect(focus.commentHeader).toContain('px-3 py-2')
+ expect(focus.commentHeaderReply).toContain('px-3 py-2')
+ expect(focus.commentHeaderMeta).toContain('pl-7')
+ expect(focus.commentHeaderMetaWithSelection).toContain('pl-[3.25rem]')
})
it('preserves the legacy flat layout tokens', () => {
diff --git a/src/renderer/src/components/right-sidebar/pr-comment-presentation.ts b/src/renderer/src/components/right-sidebar/pr-comment-presentation.ts
index 7b9a645b9..7d6ca93f2 100644
--- a/src/renderer/src/components/right-sidebar/pr-comment-presentation.ts
+++ b/src/renderer/src/components/right-sidebar/pr-comment-presentation.ts
@@ -96,6 +96,15 @@ const COMMENT_AVATAR =
const RESOLVED_SECTION_LABEL =
'text-[11px] font-semibold uppercase tracking-wider text-muted-foreground'
+// Why: markdown bodies need the secondary sidebar scale; 13px relaxed copy reads oversized in narrow comment cards.
+const CARD_COMMENT_BODY_SIZE = 'text-xs leading-5'
+const CARD_COMMENT_AUTHOR_SIZE = 'text-[13px]'
+const CARD_COMMENT_LIST_GAP = 'gap-2'
+const CARD_COMMENT_BODY_PADDING = 'px-4 py-2.5'
+const CARD_COMMENT_HEADER_PADDING = 'px-3 py-2'
+const CARD_COMMENT_META_INDENT = 'pl-7'
+const CARD_COMMENT_META_SELECTION_INDENT = 'pl-[3.25rem]'
+
const RESOLVED_SECTION_TRIGGER = cn(
RESOLVED_SECTION_LABEL,
'rounded-none border-0 bg-transparent px-3 py-2 shadow-none hover:bg-accent/40 hover:text-foreground hover:no-underline'
@@ -172,29 +181,21 @@ export function getPRCommentPresentationClasses(
}
}
- const isFocus = variant === 'focus'
- const bodySize = isFocus ? 'text-[14px] leading-relaxed' : 'text-[13px] leading-relaxed'
- const authorSize = isFocus ? 'text-[14px]' : 'text-[13px]'
- const listGap = isFocus ? 'gap-3' : 'gap-2'
- const bodyPadding = isFocus ? 'px-4 py-3' : 'px-4 py-2.5'
- const headerPadding = isFocus ? 'px-3.5 py-2.5' : 'px-3 py-2'
- const metaIndent = isFocus ? 'pl-8' : 'pl-7'
-
return {
variant,
useCardLayout: true,
- list: `flex flex-col ${listGap} px-3 py-2`,
+ list: `flex flex-col ${CARD_COMMENT_LIST_GAP} px-3 py-2`,
group: COMMENT_CARD_SURFACE,
groupStandalone: '',
groupThread: '',
commentRow: 'group/comment',
commentRowReply: `border-t ${COMMENT_CARD_DIVIDER} bg-muted/25 dark:bg-muted/10`,
- commentHeader: `flex flex-col gap-1 border-b ${COMMENT_CARD_DIVIDER} ${headerPadding}`,
- commentHeaderReply: `flex min-w-0 items-center gap-2 ${headerPadding}`,
- commentBody: `${bodyPadding} ${bodySize} text-foreground`,
- commentBodyReply: `${bodyPadding} ${bodySize} text-foreground`,
+ commentHeader: `flex flex-col gap-1 border-b ${COMMENT_CARD_DIVIDER} ${CARD_COMMENT_HEADER_PADDING}`,
+ commentHeaderReply: `flex min-w-0 items-center gap-2 ${CARD_COMMENT_HEADER_PADDING}`,
+ commentBody: `${CARD_COMMENT_BODY_PADDING} ${CARD_COMMENT_BODY_SIZE} text-foreground`,
+ commentBodyReply: `${CARD_COMMENT_BODY_PADDING} ${CARD_COMMENT_BODY_SIZE} text-foreground`,
commentBodyMarkdown: MARKDOWN_BASE,
- author: `min-w-0 flex-1 truncate ${authorSize} font-semibold text-foreground`,
+ author: `min-w-0 flex-1 truncate ${CARD_COMMENT_AUTHOR_SIZE} font-semibold text-foreground`,
authorResolved: 'text-muted-foreground',
avatar: `size-5 ${COMMENT_AVATAR}`,
avatarReply: `size-4 ${COMMENT_AVATAR}`,
@@ -224,12 +225,12 @@ export function getPRCommentPresentationClasses(
'shrink-0 rounded border border-ring/40 bg-accent px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-foreground',
commentHeaderPrimary: 'flex min-w-0 items-center gap-2',
commentHeaderMeta: cn(
- metaIndent,
+ CARD_COMMENT_META_INDENT,
'flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground'
),
// Why: checkbox (16px) + gap-2 sits before the avatar row the meta row already indents past.
commentHeaderMetaWithSelection: cn(
- isFocus ? 'pl-[3.5rem]' : 'pl-[3.25rem]',
+ CARD_COMMENT_META_SELECTION_INDENT,
'flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1 text-[11px] text-muted-foreground'
),
// Why: open state is conveyed by the status badge; a green card rail reads noisy in the sidebar.