Migrate Task Timeline tooltip to HeroUI (#3547)

* Task Timeline tooltip heroui migration

* decrease closeDelay, and changeset
This commit is contained in:
Frostbourne 2025-05-14 21:01:20 -07:00 committed by GitHub
parent 6a96c183a3
commit 4dfc1358c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 75 additions and 96 deletions

View File

@ -0,0 +1,5 @@
---
"claude-dev": patch
---
Migrate Task Timeline tooltips to HeroUI

View File

@ -95,8 +95,6 @@ const getBlockColor = (message: ClineMessage): string => {
}
const TaskTimeline: React.FC<TaskTimelineProps> = ({ messages }) => {
const [hoveredMessage, setHoveredMessage] = useState<ClineMessage | null>(null)
const [tooltipPosition, setTooltipPosition] = useState<{ x: number; y: number } | null>(null)
const containerRef = useRef<HTMLDivElement>(null)
const scrollableRef = useRef<HTMLDivElement>(null)
@ -137,29 +135,9 @@ const TaskTimeline: React.FC<TaskTimelineProps> = ({ messages }) => {
}
}, [taskTimelinePropsMessages])
const handleMouseEnter = useCallback((message: ClineMessage, event: React.MouseEvent<HTMLDivElement>) => {
setHoveredMessage(message)
const viewportWidth = window.innerWidth
const tooltipWidth = viewportWidth - TOOLTIP_MARGIN * 2
// Center the tooltip horizontally in the viewport
const x = TOOLTIP_MARGIN
setTooltipPosition({ x, y: event.clientY })
}, [])
const handleMouseLeave = useCallback(() => {
setHoveredMessage(null)
setTooltipPosition(null)
}, [])
// Calculate the item size (width of block + gap)
const itemWidth = parseInt(BLOCK_WIDTH.replace("px", "")) + parseInt(BLOCK_GAP.replace("px", ""))
// Size function for Virtuoso
const itemSize = useCallback(() => itemWidth, [itemWidth])
// Virtuoso requires a reference to scroll to the end
const virtuosoRef = useRef<any>(null)
@ -168,21 +146,21 @@ const TaskTimeline: React.FC<TaskTimelineProps> = ({ messages }) => {
(index: number) => {
const message = taskTimelinePropsMessages[index]
return (
<div
style={{
width: BLOCK_WIDTH,
height: "100%",
backgroundColor: getBlockColor(message),
flexShrink: 0,
cursor: "pointer",
marginRight: BLOCK_GAP,
}}
onMouseEnter={(e) => handleMouseEnter(message, e)}
onMouseLeave={handleMouseLeave}
/>
<TaskTimelineTooltip message={message}>
<div
style={{
width: BLOCK_WIDTH,
height: "100%",
backgroundColor: getBlockColor(message),
flexShrink: 0,
cursor: "pointer",
marginRight: BLOCK_GAP,
}}
/>
</TaskTimelineTooltip>
)
},
[taskTimelinePropsMessages, handleMouseEnter, handleMouseLeave],
[taskTimelinePropsMessages],
)
// Scroll to the end when messages change
@ -235,20 +213,6 @@ const TaskTimeline: React.FC<TaskTimelineProps> = ({ messages }) => {
increaseViewportBy={12}
fixedItemHeight={itemWidth}
/>
{hoveredMessage && containerRef.current && tooltipPosition && (
<div
style={{
position: "fixed",
left: `${tooltipPosition.x}px`,
top: `${tooltipPosition.y + 20}px`,
zIndex: 1000,
pointerEvents: "none",
width: `calc(100% - ${TOOLTIP_MARGIN * 2}px)`,
}}>
<TaskTimelineTooltip message={hoveredMessage} />
</div>
)}
</div>
)
}

View File

@ -1,14 +1,16 @@
import React from "react"
import { ClineMessage } from "@shared/ExtensionMessage"
import { COLOR_WHITE, COLOR_GRAY, COLOR_DARK_GRAY, COLOR_BEIGE, COLOR_BLUE, COLOR_RED, COLOR_PURPLE, COLOR_GREEN } from "./colors"
import { Tooltip } from "@heroui/react"
// Color mapping for different message types
interface TaskTimelineTooltipProps {
message: ClineMessage
children: React.ReactNode
}
const TaskTimelineTooltip: React.FC<TaskTimelineTooltipProps> = ({ message }) => {
const TaskTimelineTooltip = ({ message, children }: TaskTimelineTooltipProps) => {
const getMessageDescription = (message: ClineMessage): string => {
if (message.type === "say") {
switch (message.say) {
@ -227,53 +229,61 @@ const TaskTimelineTooltip: React.FC<TaskTimelineTooltipProps> = ({ message }) =>
}
return (
<div
style={{
backgroundColor: "var(--vscode-editor-background)",
color: "var(--vscode-editor-foreground)",
border: "1px solid var(--vscode-widget-border)",
borderRadius: "3px",
padding: "8px",
width: "100%", // Fill the container width
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
fontSize: "12px",
}}>
<div style={{ fontWeight: "bold", marginBottom: "4px", display: "flex", alignItems: "center" }}>
<div
style={{
width: "10px",
height: "10px",
minWidth: "10px", // Ensure fixed width
minHeight: "10px", // Ensure fixed height
borderRadius: "50%",
backgroundColor: getMessageColor(message),
marginRight: "8px",
display: "inline-block",
flexShrink: 0, // Prevent shrinking when space is limited
}}
/>
{getMessageDescription(message)}
{getTimestamp(message) && (
<span style={{ fontWeight: "normal", fontSize: "10px", marginLeft: "8px" }}>{getTimestamp(message)}</span>
)}
</div>
{getMessageContent(message) && (
<div
style={{
whiteSpace: "pre-wrap",
wordBreak: "break-word",
maxHeight: "150px",
overflowY: "auto",
fontSize: "11px",
fontFamily: "var(--vscode-editor-font-family)",
backgroundColor: "var(--vscode-textBlockQuote-background)",
padding: "4px",
borderRadius: "2px",
}}>
{getMessageContent(message)}
<Tooltip
content={
<div className="flex flex-col">
<div className="flex flex-wrap items-center font-bold mb-1">
<div className="mr-4 mb-0.5">
<div
style={{
width: "10px",
height: "10px",
minWidth: "10px", // Ensure fixed width
minHeight: "10px", // Ensure fixed height
borderRadius: "50%",
backgroundColor: getMessageColor(message),
marginRight: "8px",
display: "inline-block",
flexShrink: 0, // Prevent shrinking when space is limited
}}
/>
{getMessageDescription(message)}
</div>
{getTimestamp(message) && (
<span className="font-normal text-tiny" style={{ fontWeight: "normal", fontSize: "10px" }}>
{getTimestamp(message)}
</span>
)}
</div>
{getMessageContent(message) && (
<div
style={{
whiteSpace: "pre-wrap",
wordBreak: "break-word",
maxHeight: "150px",
overflowY: "auto",
fontSize: "11px",
fontFamily: "var(--vscode-editor-font-family)",
backgroundColor: "var(--vscode-textBlockQuote-background)",
padding: "4px",
borderRadius: "2px",
scrollbarWidth: "none",
}}>
{getMessageContent(message)}
</div>
)}
</div>
)}
</div>
}
classNames={{
base: "bg-[var(--vscode-editor-background)] text-[var(--vscode-editor-foreground)] border-[var(--vscode-widget-border)] py-1 rounded-[3px] max-w-[calc(100dvw-2rem)] text-xs",
}}
shadow="sm"
placement="bottom"
disableAnimation
closeDelay={100}
isKeyboardDismissDisabled={true}>
{children}
</Tooltip>
)
}