mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-11 07:56:50 +02:00
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:
@@ -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" />
|
||||
)}
|
||||
|
||||
@@ -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" />
|
||||
)}
|
||||
|
||||
@@ -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">
|
||||
|
||||
55
src/components/ui/IconCopyButton.tsx
Normal file
55
src/components/ui/IconCopyButton.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user