Files
orca/src/renderer/src/components/editor/DiffSectionHeader.tsx
T
gsxdsm f9e3c3945e fix(web): keep hover-reveal action icons visible on touch devices
Fix hover-reveal action icons so touch/no-hover environments keep controls visible while hover-capable desktop behavior remains unchanged.\n\nAlso covers touch-safe swap cases where passive timestamp/sparkline content shares a slot with newly visible actions.
2026-06-16 15:46:06 -07:00

90 lines
3.0 KiB
TypeScript

import { ChevronDown, ChevronRight, ExternalLink } from 'lucide-react'
import type { MouseEvent, ReactElement, ReactNode } from 'react'
import { translate } from '@/i18n/i18n'
export function DiffSectionHeader({
path,
dirty,
collapsed,
added,
removed,
onToggle,
onOpenSection,
openSectionTitle,
trailingContent
}: {
path: string
dirty: boolean
collapsed: boolean
added: number
removed: number
onToggle: () => void
onOpenSection: (event: MouseEvent) => void
openSectionTitle: string
trailingContent?: ReactNode
}): ReactElement {
return (
<div
className="sticky top-0 z-10 bg-background flex items-center w-full px-3 py-1.5 text-left text-xs hover:bg-accent transition-colors group cursor-pointer"
onClick={onToggle}
>
<span className="min-w-0 flex-1 truncate text-muted-foreground">
<span
role="button"
tabIndex={0}
className="cursor-copy hover:underline"
onMouseDown={(event) => {
event.preventDefault()
event.stopPropagation()
}}
onClick={(event) => {
event.preventDefault()
event.stopPropagation()
// Why: stop both mouse-down and click on the path affordance so
// the parent section-toggle row cannot consume the interaction.
void window.api.ui.writeClipboardText(path).catch((error) => {
console.error('Failed to copy diff path:', error)
})
}}
onKeyDown={(event) => {
if (event.key !== 'Enter' && event.key !== ' ') {
return
}
event.preventDefault()
event.stopPropagation()
void window.api.ui.writeClipboardText(path).catch((error) => {
console.error('Failed to copy diff path:', error)
})
}}
title={translate('auto.components.editor.DiffSectionHeader.8915726e93', 'Copy path')}
>
{path}
</span>
{dirty && <span className="font-medium ml-1">M</span>}
{(added > 0 || removed > 0) && (
<span className="tabular-nums ml-2">
{added > 0 && <span className="text-green-600 dark:text-green-500">+{added}</span>}
{added > 0 && removed > 0 && <span> </span>}
{removed > 0 && <span className="text-red-500">-{removed}</span>}
</span>
)}
</span>
<div className="flex items-center gap-1 shrink-0 ml-2">
{trailingContent}
<button
className="p-0.5 rounded text-muted-foreground hover:text-foreground can-hover:opacity-0 group-hover:opacity-100 transition-opacity"
onClick={onOpenSection}
title={openSectionTitle}
>
<ExternalLink className="size-3.5" />
</button>
{collapsed ? (
<ChevronRight className="size-3.5 shrink-0 text-muted-foreground" />
) : (
<ChevronDown className="size-3.5 shrink-0 text-muted-foreground" />
)}
</div>
</div>
)
}