Refine workspace hovercard section indentation (#2745)

This commit is contained in:
Neil
2026-05-24 01:17:35 -07:00
committed by GitHub
parent 476f367c9d
commit 7c1910a462
4 changed files with 55 additions and 20 deletions
@@ -0,0 +1,23 @@
import React from 'react'
import { cn } from '@/lib/utils'
type WorktreeCardDetailSectionProps = React.HTMLAttributes<HTMLElement>
type WorktreeCardDetailSectionContentProps = React.HTMLAttributes<HTMLDivElement>
export function WorktreeCardDetailSection({
className,
...props
}: WorktreeCardDetailSectionProps): React.JSX.Element {
return <section className={cn('space-y-1.5', className)} {...props} />
}
export function WorktreeCardDetailSectionContent({
className,
...props
}: WorktreeCardDetailSectionContentProps): React.JSX.Element {
return (
// Why: section titles stay at hovercard level 0; only each section's body
// is inset so stacked metadata remains visually scannable.
<div className={cn('border-l border-border/70 pl-3', className)} {...props} />
)
}
@@ -13,6 +13,10 @@ import { SelectedTextCopyMenu } from '@/components/SelectedTextCopyMenu'
import CommentMarkdown from './CommentMarkdown'
import { PullRequestIcon } from './WorktreeCardHelpers'
import { WORKTREE_NATIVE_CONTEXT_MENU_ATTR } from './WorktreeContextMenu'
import {
WorktreeCardDetailSection,
WorktreeCardDetailSectionContent
} from './WorktreeCardDetailSection'
import {
IssueStateBadge,
LinearStateBadge,
@@ -300,7 +304,7 @@ export function WorktreeCardDetailsHover({
>
<SelectedTextCopyMenu className="space-y-3">
{issue && (
<section className="space-y-1.5">
<WorktreeCardDetailSection>
<DetailHeader
icon={<CircleDot className="size-3 text-muted-foreground" />}
label={`Issue #${issue.number}`}
@@ -325,7 +329,7 @@ export function WorktreeCardDetailsHover({
</>
}
/>
<div className="space-y-1.5">
<WorktreeCardDetailSectionContent className="space-y-1.5">
<div className="text-[13px] font-semibold leading-snug text-foreground break-words">
{issue.title}
</div>
@@ -339,12 +343,12 @@ export function WorktreeCardDetailsHover({
))}
</div>
)}
</div>
</section>
</WorktreeCardDetailSectionContent>
</WorktreeCardDetailSection>
)}
{linearIssue && (
<section className="space-y-1.5">
<WorktreeCardDetailSection>
<DetailHeader
icon={<LinearIcon className="size-3 text-muted-foreground" />}
label={`Linear ${linearIssue.identifier}`}
@@ -366,7 +370,7 @@ export function WorktreeCardDetailsHover({
</>
}
/>
<div className="space-y-1.5">
<WorktreeCardDetailSectionContent className="space-y-1.5">
<div className="text-[13px] font-semibold leading-snug text-foreground break-words">
{linearIssue.title}
</div>
@@ -383,12 +387,12 @@ export function WorktreeCardDetailsHover({
))}
</div>
)}
</div>
</section>
</WorktreeCardDetailSectionContent>
</WorktreeCardDetailSection>
)}
{review && reviewLabel && reviewProvider && (
<section className="space-y-1.5">
<WorktreeCardDetailSection>
<DetailHeader
icon={<ReviewIcon review={review} className="size-3" />}
label={`${reviewLabel} #${review.number}`}
@@ -410,7 +414,7 @@ export function WorktreeCardDetailsHover({
</>
}
/>
<div className="space-y-1.5">
<WorktreeCardDetailSectionContent className="space-y-1.5">
<div className="text-[13px] font-semibold leading-snug text-foreground break-words">
{review.title}
</div>
@@ -420,12 +424,12 @@ export function WorktreeCardDetailsHover({
<ReviewChecksBadge status={review.status} />
</div>
)}
</div>
</section>
</WorktreeCardDetailSectionContent>
</WorktreeCardDetailSection>
)}
{hasComment(comment) && (
<section className="space-y-1.5">
<WorktreeCardDetailSection>
<DetailHeader
icon={<StickyNote className="size-3 text-muted-foreground" />}
label="Notes"
@@ -435,13 +439,13 @@ export function WorktreeCardDetailsHover({
</MetadataActionIcon>
}
/>
<div className="space-y-2">
<WorktreeCardDetailSectionContent className="space-y-2">
<CommentMarkdown
content={comment ?? ''}
className="text-[11.5px] text-foreground break-words leading-normal [&_.comment-md-p]:block [&_.comment-md-p+.comment-md-p]:mt-1"
/>
</div>
</section>
</WorktreeCardDetailSectionContent>
</WorktreeCardDetailSection>
)}
{detailsAfter}
@@ -47,5 +47,9 @@ describe('WorktreeCardPortsDetails', () => {
expect(markup).toContain('dev.preview.localhost:58941')
expect(markup).toContain('aria-label="Copy dev.preview.localhost:58941"')
expect(markup).toContain(
'<section class="space-y-1.5"><div class="flex items-center gap-1.5 px-1'
)
expect(markup).toContain('class="border-l border-border/70 pl-3 space-y-0.5"')
})
})
@@ -18,6 +18,10 @@ import {
import { addressForPort } from '@/lib/workspace-port-urls'
import type { WorkspacePort } from '../../../../shared/workspace-ports'
import { WORKTREE_NATIVE_CONTEXT_MENU_ATTR } from './WorktreeContextMenu'
import {
WorktreeCardDetailSection,
WorktreeCardDetailSectionContent
} from './WorktreeCardDetailSection'
type WorktreeCardPortsProps = {
ports: WorkspacePort[]
@@ -213,7 +217,7 @@ export function WorktreeCardPortsDetails({
}
return (
<section className="space-y-1.5">
<WorktreeCardDetailSection>
<div className="flex items-center gap-1.5 px-1 text-[11px] font-semibold uppercase tracking-[0.05em] text-muted-foreground">
<Plug className="size-3" />
<span>Live Ports</span>
@@ -224,12 +228,12 @@ export function WorktreeCardPortsDetails({
<span className="font-normal tabular-nums text-muted-foreground/70">{ports.length}</span>
</div>
</div>
<div className="space-y-0.5">
<WorktreeCardDetailSectionContent className="space-y-0.5">
{ports.map((port) => (
<WorktreePortRow key={port.id} port={port} />
))}
</div>
</section>
</WorktreeCardDetailSectionContent>
</WorktreeCardDetailSection>
)
}