refactor: improve styling and layout in DiffModal and DiffViewer components

- Reduced padding and adjusted spacing in the DiffModal for a more compact layout.
- Updated text sizes and line heights in the DiffViewer for better readability.
- Removed unnecessary dialog components to streamline the structure.
- Enhanced the file header layout for improved visual clarity and interaction.
This commit is contained in:
d-kimsuon
2025-10-19 00:38:36 +09:00
parent 6f7ef2a189
commit 30a92c48d4
2 changed files with 44 additions and 71 deletions

View File

@@ -4,12 +4,7 @@ import { FileText, GitBranch, Loader2, RefreshCcwIcon } from "lucide-react";
import type { FC } from "react"; import type { FC } from "react";
import { useCallback, useEffect, useId, useState } from "react"; import { useCallback, useEffect, useId, useState } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import { Dialog, DialogContent } from "@/components/ui/dialog";
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { import {
Select, Select,
SelectContent, SelectContent,
@@ -31,7 +26,7 @@ const DiffSummaryComponent: FC<DiffSummaryProps> = ({ summary, className }) => {
return ( return (
<div <div
className={cn( className={cn(
"bg-gray-50 dark:bg-gray-800 rounded-lg p-4 border border-gray-200 dark:border-gray-700", "bg-gray-50 dark:bg-gray-800 rounded-lg p-2 border border-gray-200 dark:border-gray-700",
className, className,
)} )}
> >
@@ -90,7 +85,7 @@ const RefSelector: FC<RefSelectorProps> = ({
}; };
return ( return (
<div className="space-y-2"> <div className="space-y-1">
<label <label
htmlFor={id} htmlFor={id}
className="text-sm font-medium text-gray-700 dark:text-gray-300" className="text-sm font-medium text-gray-700 dark:text-gray-300"
@@ -198,12 +193,8 @@ export const DiffModal: FC<DiffModalProps> = ({
return ( return (
<Dialog open={isOpen} onOpenChange={onOpenChange}> <Dialog open={isOpen} onOpenChange={onOpenChange}>
<DialogContent className="max-w-7xl w-[95vw] h-[90vh] overflow-hidden flex flex-col px-2 md:px-8"> <DialogContent className="max-w-7xl w-[95vw] h-[90vh] overflow-hidden flex flex-col px-2 md:px-8">
<DialogHeader> <div className="flex flex-col sm:flex-row gap-2 sm:items-end">
<DialogTitle>Preview Changes</DialogTitle> <div className="flex flex-col sm:flex-row gap-2 flex-1">
</DialogHeader>
<div className="flex flex-col sm:flex-row gap-3 sm:items-end">
<div className="flex flex-col sm:flex-row gap-3 flex-1">
<RefSelector <RefSelector
label="Compare from" label="Compare from"
value={compareFrom} value={compareFrom}
@@ -247,7 +238,7 @@ export const DiffModal: FC<DiffModalProps> = ({
)} )}
{diffData?.success && ( {diffData?.success && (
<> <div className="flex-1 overflow-auto">
<DiffSummaryComponent <DiffSummaryComponent
summary={{ summary={{
filesChanged: diffData.data.files.length, filesChanged: diffData.data.files.length,
@@ -265,9 +256,10 @@ export const DiffModal: FC<DiffModalProps> = ({
linesDeleted: diff.file.deletions, linesDeleted: diff.file.deletions,
})), })),
}} }}
className="mb-3"
/> />
<div className="flex-1 overflow-auto space-y-6"> <div className="space-y-3">
{diffData.data.diffs.map((diff) => ( {diffData.data.diffs.map((diff) => (
<DiffViewer <DiffViewer
key={diff.file.filePath} key={diff.file.filePath}
@@ -285,7 +277,7 @@ export const DiffModal: FC<DiffModalProps> = ({
/> />
))} ))}
</div> </div>
</> </div>
)} )}
{isDiffLoading && ( {isDiffLoading && (

View File

@@ -27,7 +27,7 @@ const DiffHunkComponent: FC<DiffHunkProps> = ({ hunk }) => {
{hunk.lines.map((line, index) => ( {hunk.lines.map((line, index) => (
<div <div
key={`old-${line.oldLineNumber}-${index}`} key={`old-${line.oldLineNumber}-${index}`}
className="px-2 py-1 text-sm text-gray-400 dark:text-gray-600 font-mono text-right h-[28px]" className="px-1 py-0.5 text-xs text-gray-400 dark:text-gray-600 font-mono text-right leading-tight"
> >
{line.type !== "added" && {line.type !== "added" &&
line.type !== "hunk" && line.type !== "hunk" &&
@@ -42,7 +42,7 @@ const DiffHunkComponent: FC<DiffHunkProps> = ({ hunk }) => {
{hunk.lines.map((line, index) => ( {hunk.lines.map((line, index) => (
<div <div
key={`new-${line.newLineNumber}-${index}`} key={`new-${line.newLineNumber}-${index}`}
className="px-2 py-1 text-sm text-gray-400 dark:text-gray-600 font-mono text-right h-[28px]" className="px-1 py-0.5 text-xs text-gray-400 dark:text-gray-600 font-mono text-right leading-tight"
> >
{line.type !== "deleted" && {line.type !== "deleted" &&
line.type !== "hunk" && line.type !== "hunk" &&
@@ -70,8 +70,8 @@ const DiffHunkComponent: FC<DiffHunkProps> = ({ hunk }) => {
line.type === "unchanged", line.type === "unchanged",
})} })}
> >
<div className="flex-1 px-2 py-1"> <div className="flex-1 px-2 py-0.5">
<span className="font-mono text-sm whitespace-pre block"> <span className="font-mono text-xs whitespace-pre block leading-tight">
<span <span
className={cn({ className={cn({
"text-green-600 dark:text-green-400": line.type === "added", "text-green-600 dark:text-green-400": line.type === "added",
@@ -121,13 +121,6 @@ const FileHeader: FC<FileHeaderProps> = ({
return <span className="text-gray-600 dark:text-gray-400">M</span>; return <span className="text-gray-600 dark:text-gray-400">M</span>;
}; };
const getFileStatusText = () => {
if (fileDiff.isNew) return "added";
if (fileDiff.isDeleted) return "deleted";
if (fileDiff.isRenamed) return `renamed from ${fileDiff.oldFilename ?? ""}`;
return "modified";
};
const handleCopyFilename = async (e: React.MouseEvent) => { const handleCopyFilename = async (e: React.MouseEvent) => {
e.stopPropagation(); e.stopPropagation();
try { try {
@@ -142,52 +135,40 @@ const FileHeader: FC<FileHeaderProps> = ({
return ( return (
<Button <Button
onClick={onToggleCollapse} onClick={onToggleCollapse}
className="w-full bg-gray-50 dark:bg-gray-800 px-4 py-4 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors min-h-[4rem]" className="w-full bg-gray-50 dark:bg-gray-800 px-3 py-1.5 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors sticky top-0 z-20"
> >
<div className="w-full space-y-1"> <div className="w-full flex items-center gap-2">
{/* Row 1: icon, status, and stats */} {isCollapsed ? (
<div className="flex items-center justify-between"> <ChevronRightIcon className="w-4 h-4 text-gray-500 flex-shrink-0" />
<div className="flex items-center gap-2"> ) : (
{isCollapsed ? ( <ChevronDownIcon className="w-4 h-4 text-gray-500 flex-shrink-0" />
<ChevronRightIcon className="w-4 h-4 text-gray-500" /> )}
) : ( <div className="w-5 h-5 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center text-xs font-mono flex-shrink-0">
<ChevronDownIcon className="w-4 h-4 text-gray-500" /> {getFileStatusIcon()}
)} </div>
<div className="w-6 h-6 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center text-xs font-mono"> <span className="font-mono text-xs font-medium text-black dark:text-white text-left truncate flex-1 min-w-0">
{getFileStatusIcon()} {fileDiff.filename}
</div> </span>
<span className="text-xs text-gray-500 dark:text-gray-400"> <div className="flex items-center gap-3 text-xs text-gray-500 dark:text-gray-400 flex-shrink-0">
{getFileStatusText()} {fileDiff.linesAdded > 0 && (
<span className="text-green-600 dark:text-green-400">
+{fileDiff.linesAdded}
</span> </span>
</div> )}
<div className="flex items-center gap-4 text-xs text-gray-500 dark:text-gray-400"> {fileDiff.linesDeleted > 0 && (
{fileDiff.linesAdded > 0 && ( <span className="text-red-600 dark:text-red-400">
<span className="text-green-600 dark:text-green-400"> -{fileDiff.linesDeleted}
+{fileDiff.linesAdded} </span>
</span> )}
)}
{fileDiff.linesDeleted > 0 && (
<span className="text-red-600 dark:text-red-400">
-{fileDiff.linesDeleted}
</span>
)}
</div>
</div>
{/* Row 2: filename with copy button */}
<div className="w-full flex items-center gap-2">
<span className="font-mono text-sm font-medium text-black dark:text-white text-left truncate flex-1 min-w-0">
{fileDiff.filename}
</span>
<Button
onClick={handleCopyFilename}
variant="ghost"
size="sm"
className="flex-shrink-0 p-1 h-6 w-6 hover:bg-gray-200 dark:hover:bg-gray-600"
>
<CopyIcon className="w-3 h-3 text-gray-500 dark:text-gray-400" />
</Button>
</div> </div>
<Button
onClick={handleCopyFilename}
variant="ghost"
size="sm"
className="flex-shrink-0 p-1 h-5 w-5 hover:bg-gray-200 dark:hover:bg-gray-600"
>
<CopyIcon className="w-3 h-3 text-gray-500 dark:text-gray-400" />
</Button>
</div> </div>
{fileDiff.isBinary && ( {fileDiff.isBinary && (
<div className="mt-2 text-xs text-gray-500 dark:text-gray-400 text-left"> <div className="mt-2 text-xs text-gray-500 dark:text-gray-400 text-left">