refactor: create IconCopyButton component and use CopyCheck consistently

- Add IconCopyButton component for reusable icon-only copy buttons
- Refactor RepositoryFilesSection to use IconCopyButton
- Replace Check with CopyCheck in ChatMessageContextMenu
- Replace Check with CopyCheck in BaseEventRenderer
- Use text-success instead of text-green-500 for consistency
This commit is contained in:
Claude
2026-01-30 10:07:35 +00:00
parent 55fb95789b
commit 8b198f1a26
4 changed files with 67 additions and 29 deletions

View File

@@ -12,7 +12,7 @@ import {
} from "@/components/ui/context-menu";
import {
Copy,
Check,
CopyCheck,
FileJson,
ExternalLink,
Reply,
@@ -212,7 +212,7 @@ export function ChatMessageContextMenu({
</ContextMenuItem>
<ContextMenuItem onClick={copyEventId}>
{copied ? (
<Check className="size-4 mr-2 text-green-500" />
<CopyCheck className="size-4 mr-2 text-success" />
) : (
<Copy className="size-4 mr-2" />
)}

View File

@@ -18,7 +18,7 @@ import {
import {
Menu,
Copy,
Check,
CopyCheck,
FileJson,
ExternalLink,
Zap,
@@ -267,7 +267,7 @@ export function EventMenu({
<DropdownMenuSeparator />
<DropdownMenuItem onClick={copyEventId}>
{copied ? (
<Check className="size-4 mr-2 text-green-500" />
<CopyCheck className="size-4 mr-2 text-success" />
) : (
<Copy className="size-4 mr-2" />
)}
@@ -433,7 +433,7 @@ export function EventContextMenu({
<ContextMenuSeparator />
<ContextMenuItem onClick={copyEventId}>
{copied ? (
<Check className="size-4 mr-2 text-green-500" />
<CopyCheck className="size-4 mr-2 text-success" />
) : (
<Copy className="size-4 mr-2" />
)}

View File

@@ -1,16 +1,9 @@
import { useState } from "react";
import {
FolderGit2,
AlertCircle,
FileQuestion,
Binary,
Copy,
Check,
} from "lucide-react";
import { FolderGit2, AlertCircle, FileQuestion, Binary } from "lucide-react";
import { useGitTree } from "@/hooks/useGitTree";
import { useGitBlob } from "@/hooks/useGitBlob";
import { useCopy } from "@/hooks/useCopy";
import { FileTreeView } from "@/components/ui/FileTreeView";
import { IconCopyButton } from "@/components/ui/IconCopyButton";
import { SyntaxHighlight } from "@/components/SyntaxHighlight";
import { Skeleton } from "@/components/ui/skeleton/Skeleton";
import { cn } from "@/lib/utils";
@@ -79,9 +72,6 @@ export function RepositoryFilesSection({
? getExtension(selectedFile.name) || null
: null;
// Copy functionality for file content
const { copy, copied } = useCopy();
const handleFileSelect = (file: SelectedFile) => {
setSelectedFile(file);
};
@@ -185,18 +175,11 @@ export function RepositoryFilesSection({
<span className="text-xs font-mono text-muted-foreground truncate">
{selectedFile.path}
</span>
<button
type="button"
onClick={() => copy(fileContent)}
className="flex-shrink-0 p-1 rounded hover:bg-muted/50 text-muted-foreground hover:text-foreground transition-colors"
title="Copy file content"
>
{copied ? (
<Check className="size-3.5 text-success" />
) : (
<Copy className="size-3.5" />
)}
</button>
<IconCopyButton
text={fileContent}
size="sm"
label="Copy file content"
/>
</div>
{rawContent && (
<span className="text-xs text-muted-foreground flex-shrink-0">

View File

@@ -0,0 +1,55 @@
import { Copy, CopyCheck } from "lucide-react";
import { useCopy } from "@/hooks/useCopy";
import { cn } from "@/lib/utils";
type IconSize = "xs" | "sm" | "md" | "lg";
interface IconCopyButtonProps {
/** Text to copy to clipboard */
text: string;
/** Icon size preset */
size?: IconSize;
/** Additional class names for the button */
className?: string;
/** Tooltip/aria-label text */
label?: string;
}
const sizeClasses: Record<IconSize, string> = {
xs: "size-3",
sm: "size-3.5",
md: "size-4",
lg: "size-5 md:size-4",
};
/**
* Tiny icon-only copy button for inline use
* Uses Copy/CopyCheck icons with consistent styling
*/
export function IconCopyButton({
text,
size = "sm",
className,
label = "Copy",
}: IconCopyButtonProps) {
const { copy, copied } = useCopy();
return (
<button
type="button"
onClick={() => copy(text)}
className={cn(
"flex-shrink-0 p-1 rounded hover:bg-muted/50 text-muted-foreground hover:text-foreground transition-colors",
className,
)}
title={label}
aria-label={label}
>
{copied ? (
<CopyCheck className={cn(sizeClasses[size], "text-success")} />
) : (
<Copy className={sizeClasses[size]} />
)}
</button>
);
}