mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
Refine workspace hovercard section indentation (#2745)
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user