mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-10-08 03:07:53 +00:00
feat: add file path tooltips with centralized PathTooltip component (#9030)
- Add PathTooltip component that wraps StandardTooltip with proper styling - Use maxWidth='min(300px,100vw)' via inline style to override defaults - Apply '[text-wrap:wrap]' class to override text-balance behavior - Add formatPathTooltip helper for consistent path content formatting - Update CodeAccordian, ChatRow, and BatchFilePermission to use PathTooltip - Centralizes tooltip behavior and reduces duplication Supersedes PR #8797.
This commit is contained in:
parent
e25b4e62d1
commit
f1caf3f36e
5 changed files with 113 additions and 15 deletions
|
|
@ -2,7 +2,8 @@ import { memo } from "react"
|
|||
|
||||
import { ToolUseBlock, ToolUseBlockHeader } from "../common/ToolUseBlock"
|
||||
import { vscode } from "@src/utils/vscode"
|
||||
import { removeLeadingNonAlphanumeric } from "@src/utils/removeLeadingNonAlphanumeric"
|
||||
import { formatPathTooltip } from "@src/utils/formatPathTooltip"
|
||||
import { PathTooltip } from "../ui/PathTooltip"
|
||||
|
||||
interface FilePermissionItem {
|
||||
path: string
|
||||
|
|
@ -35,10 +36,18 @@ export const BatchFilePermission = memo(({ files = [], onPermissionResponse, ts
|
|||
<ToolUseBlockHeader
|
||||
onClick={() => vscode.postMessage({ type: "openFile", text: file.content })}>
|
||||
{file.path?.startsWith(".") && <span>.</span>}
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis text-left mr-2 rtl">
|
||||
{removeLeadingNonAlphanumeric(file.path ?? "") + "\u200E"}
|
||||
{file.lineSnippet && ` ${file.lineSnippet}`}
|
||||
</span>
|
||||
<PathTooltip
|
||||
content={formatPathTooltip(
|
||||
file.path,
|
||||
file.lineSnippet ? ` ${file.lineSnippet}` : undefined,
|
||||
)}>
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis text-left mr-2 rtl">
|
||||
{formatPathTooltip(
|
||||
file.path,
|
||||
file.lineSnippet ? ` ${file.lineSnippet}` : undefined,
|
||||
)}
|
||||
</span>
|
||||
</PathTooltip>
|
||||
<div className="flex-grow"></div>
|
||||
<span className="codicon codicon-link-external text-[13.5px] my-[1px]" />
|
||||
</ToolUseBlockHeader>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import { safeJsonParse } from "@roo/safeJsonParse"
|
|||
import { useExtensionState } from "@src/context/ExtensionStateContext"
|
||||
import { findMatchingResourceOrTemplate } from "@src/utils/mcp"
|
||||
import { vscode } from "@src/utils/vscode"
|
||||
import { removeLeadingNonAlphanumeric } from "@src/utils/removeLeadingNonAlphanumeric"
|
||||
import { formatPathTooltip } from "@src/utils/formatPathTooltip"
|
||||
import { getLanguageFromPath } from "@src/utils/getLanguageFromPath"
|
||||
|
||||
import { ToolUseBlock, ToolUseBlockHeader } from "../common/ToolUseBlock"
|
||||
|
|
@ -61,6 +61,7 @@ import {
|
|||
MessageCircle,
|
||||
} from "lucide-react"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { PathTooltip } from "../ui/PathTooltip"
|
||||
|
||||
interface ChatRowProps {
|
||||
message: ClineMessage
|
||||
|
|
@ -552,10 +553,11 @@ export const ChatRowContent = ({
|
|||
className="group"
|
||||
onClick={() => vscode.postMessage({ type: "openFile", text: tool.content })}>
|
||||
{tool.path?.startsWith(".") && <span>.</span>}
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis text-left mr-2 rtl">
|
||||
{removeLeadingNonAlphanumeric(tool.path ?? "") + "\u200E"}
|
||||
{tool.reason}
|
||||
</span>
|
||||
<PathTooltip content={formatPathTooltip(tool.path, tool.reason)}>
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis text-left mr-2 rtl">
|
||||
{formatPathTooltip(tool.path, tool.reason)}
|
||||
</span>
|
||||
</PathTooltip>
|
||||
<div style={{ flexGrow: 1 }}></div>
|
||||
<SquareArrowOutUpRight
|
||||
className="w-4 shrink-0 codicon codicon-link-external opacity-0 group-hover:opacity-100 transition-opacity"
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ import { memo, useMemo } from "react"
|
|||
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react"
|
||||
import { type ToolProgressStatus } from "@roo-code/types"
|
||||
import { getLanguageFromPath } from "@src/utils/getLanguageFromPath"
|
||||
import { removeLeadingNonAlphanumeric } from "@src/utils/removeLeadingNonAlphanumeric"
|
||||
import { formatPathTooltip } from "@src/utils/formatPathTooltip"
|
||||
|
||||
import { ToolUseBlock, ToolUseBlockHeader } from "./ToolUseBlock"
|
||||
import CodeBlock from "./CodeBlock"
|
||||
import { PathTooltip } from "../ui/PathTooltip"
|
||||
|
||||
interface CodeAccordianProps {
|
||||
path?: string
|
||||
|
|
@ -44,7 +45,9 @@ const CodeAccordian = ({
|
|||
{header ? (
|
||||
<div className="flex items-center">
|
||||
<span className="codicon codicon-server mr-1.5"></span>
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis mr-2">{header}</span>
|
||||
<PathTooltip content={header}>
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis mr-2">{header}</span>
|
||||
</PathTooltip>
|
||||
</div>
|
||||
) : isFeedback ? (
|
||||
<div className="flex items-center">
|
||||
|
|
@ -56,9 +59,11 @@ const CodeAccordian = ({
|
|||
) : (
|
||||
<>
|
||||
{path?.startsWith(".") && <span>.</span>}
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis text-left mr-2 rtl">
|
||||
{removeLeadingNonAlphanumeric(path ?? "") + "\u200E"}
|
||||
</span>
|
||||
<PathTooltip content={formatPathTooltip(path)}>
|
||||
<span className="whitespace-nowrap overflow-hidden text-ellipsis text-left mr-2 rtl">
|
||||
{formatPathTooltip(path)}
|
||||
</span>
|
||||
</PathTooltip>
|
||||
</>
|
||||
)}
|
||||
<div className="flex-grow-1" />
|
||||
|
|
|
|||
54
webview-ui/src/components/ui/PathTooltip.tsx
Normal file
54
webview-ui/src/components/ui/PathTooltip.tsx
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import { ReactNode } from "react"
|
||||
import { StandardTooltip } from "./standard-tooltip"
|
||||
|
||||
interface PathTooltipProps {
|
||||
/** The file path or content to display in the tooltip */
|
||||
content: string
|
||||
/** The element(s) that trigger the tooltip */
|
||||
children: ReactNode
|
||||
/** The preferred side of the trigger to render the tooltip */
|
||||
side?: "top" | "right" | "bottom" | "left"
|
||||
/** The preferred alignment against the trigger */
|
||||
align?: "start" | "center" | "end"
|
||||
/** Distance in pixels from the trigger */
|
||||
sideOffset?: number
|
||||
/** Whether the trigger should be rendered as a child */
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* PathTooltip component specifically designed for displaying file paths with appropriate
|
||||
* wrapping and responsive width behavior. Use this for truncated file paths that need
|
||||
* tooltips to show the full path.
|
||||
*
|
||||
* Features:
|
||||
* - Responsive max-width that adapts to panel size (max 300px on wide panels, 100vw on narrow)
|
||||
* - Uses text-wrap instead of text-balance to minimize whitespace
|
||||
* - Leverages existing break-words CSS for natural line breaking at path separators
|
||||
*
|
||||
* @example
|
||||
* <PathTooltip content="/very/long/file/path.tsx">
|
||||
* <span className="truncate">...path.tsx</span>
|
||||
* </PathTooltip>
|
||||
*/
|
||||
export function PathTooltip({
|
||||
content,
|
||||
children,
|
||||
side = "top",
|
||||
align = "start",
|
||||
sideOffset = 4,
|
||||
asChild = true,
|
||||
}: PathTooltipProps) {
|
||||
return (
|
||||
<StandardTooltip
|
||||
content={content}
|
||||
side={side}
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className="[text-wrap:wrap]"
|
||||
maxWidth="min(300px,100vw)"
|
||||
asChild={asChild}>
|
||||
{children}
|
||||
</StandardTooltip>
|
||||
)
|
||||
}
|
||||
28
webview-ui/src/utils/formatPathTooltip.ts
Normal file
28
webview-ui/src/utils/formatPathTooltip.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import { removeLeadingNonAlphanumeric } from "./removeLeadingNonAlphanumeric"
|
||||
|
||||
/**
|
||||
* Formats a file path for display in tooltips with consistent formatting.
|
||||
*
|
||||
* @param path - The file path to format
|
||||
* @param additionalContent - Optional additional content to append (e.g., line snippets, reasons)
|
||||
* @returns Formatted string ready for tooltip display
|
||||
*
|
||||
* @example
|
||||
* formatPathTooltip("/src/components/MyComponent.tsx")
|
||||
* // Returns: "src/components/MyComponent.tsx" + U+200E
|
||||
*
|
||||
* @example
|
||||
* formatPathTooltip("/src/utils/helper.ts", ":42-45")
|
||||
* // Returns: "src/utils/helper.ts:42-45" + U+200E
|
||||
*/
|
||||
export function formatPathTooltip(path?: string, additionalContent?: string): string {
|
||||
if (!path) return ""
|
||||
|
||||
const formattedPath = removeLeadingNonAlphanumeric(path) + "\u200E"
|
||||
|
||||
if (additionalContent) {
|
||||
return formattedPath + additionalContent
|
||||
}
|
||||
|
||||
return formattedPath
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue