-
Notifications
You must be signed in to change notification settings - Fork 22
Open
Description
Feature Request
Display a special icon/indicator for deleted files in the PR diff view, similar to how newly added files are shown with a special icon.
Current Behavior
- New/added files may have a special icon or indicator
- Deleted files don't have a clear visual distinction
- Users need to read the diff header or stats to know a file was deleted
Expected Behavior
- Deleted files should have a distinctive icon (e.g., 🗑️, ❌, or a red minus icon)
- Visual consistency with how added files are displayed
- Clear visual hierarchy: Added (green/+), Modified (yellow/~), Deleted (red/-)
Implementation
File Status Icons
interface FileStatus {
type: 'added' | 'modified' | 'deleted' | 'renamed' | 'copied';
icon: string;
className: string;
label: string;
}
const FILE_STATUS_CONFIG: Record<string, FileStatus> = {
added: {
type: 'added',
icon: '✨', // or '➕' or custom SVG
className: 'file-added',
label: 'New file'
},
modified: {
type: 'modified',
icon: '📝', // or '✏️' or custom SVG
className: 'file-modified',
label: 'Modified'
},
deleted: {
type: 'deleted',
icon: '🗑️', // or '❌' or '➖' or custom SVG
className: 'file-deleted',
label: 'Deleted'
},
renamed: {
type: 'renamed',
icon: '📋', // or '➡️' or custom SVG
className: 'file-renamed',
label: 'Renamed'
},
copied: {
type: 'copied',
icon: '📄', // or custom SVG
className: 'file-copied',
label: 'Copied'
}
};Component Implementation
function FileListItem({ file }) {
const status = getFileStatus(file);
return (
<div className={`file-item ${status.className}`}>
<span className="file-status-icon" title={status.label}>
{status.icon}
</span>
<span className="file-path">
{file.status === 'renamed' ? (
<>
<span className="old-name">{file.previous_filename}</span>
<span className="rename-arrow">→</span>
<span className="new-name">{file.filename}</span>
</>
) : (
<span className={file.status === 'deleted' ? 'strikethrough' : ''}>
{file.filename}
</span>
)}
</span>
<span className="file-stats">
{file.status !== 'deleted' && (
<span className="additions">+{file.additions}</span>
)}
{file.status !== 'added' && (
<span className="deletions">-{file.deletions}</span>
)}
</span>
</div>
);
}
function getFileStatus(file): FileStatus {
if (file.status === 'removed') {
return FILE_STATUS_CONFIG.deleted;
}
if (file.status === 'added') {
return FILE_STATUS_CONFIG.added;
}
if (file.status === 'renamed') {
return FILE_STATUS_CONFIG.renamed;
}
if (file.status === 'copied') {
return FILE_STATUS_CONFIG.copied;
}
return FILE_STATUS_CONFIG.modified;
}Styling
.file-item {
display: flex;
align-items: center;
padding: 8px 12px;
border-radius: 4px;
transition: background-color 0.2s;
}
.file-item:hover {
background-color: var(--hover-bg);
}
.file-status-icon {
margin-right: 8px;
font-size: 16px;
flex-shrink: 0;
}
/* File status specific styles */
.file-added {
border-left: 3px solid var(--color-success);
}
.file-added .file-status-icon {
color: var(--color-success);
}
.file-modified {
border-left: 3px solid var(--color-warning);
}
.file-modified .file-status-icon {
color: var(--color-warning);
}
.file-deleted {
border-left: 3px solid var(--color-danger);
opacity: 0.8;
}
.file-deleted .file-status-icon {
color: var(--color-danger);
}
.file-deleted .file-path {
text-decoration: line-through;
opacity: 0.7;
}
.file-renamed {
border-left: 3px solid var(--color-info);
}
.file-renamed .file-status-icon {
color: var(--color-info);
}
.rename-arrow {
margin: 0 8px;
color: var(--text-secondary);
}
/* Alternative: Use background colors */
.file-added-alt {
background-color: rgba(46, 160, 67, 0.1);
}
.file-deleted-alt {
background-color: rgba(248, 81, 73, 0.1);
}
.file-modified-alt {
background-color: rgba(250, 179, 0, 0.1);
}Alternative Icon Approaches
1. SVG Icons
const FileStatusIcons = {
added: (
<svg className="file-icon added" viewBox="0 0 16 16">
<path d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2Z"/>
</svg>
),
deleted: (
<svg className="file-icon deleted" viewBox="0 0 16 16">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1z"/>
</svg>
),
modified: (
<svg className="file-icon modified" viewBox="0 0 16 16">
<path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z"/>
</svg>
)
};2. Text Indicators
const FileStatusBadges = {
added: <span className="badge badge-success">NEW</span>,
deleted: <span className="badge badge-danger">DELETED</span>,
modified: <span className="badge badge-warning">MODIFIED</span>,
renamed: <span className="badge badge-info">RENAMED</span>
};Diff Header Enhancement
function DiffFileHeader({ file }) {
const status = getFileStatus(file);
return (
<div className={`diff-header ${status.className}`}>
<div className="diff-header-content">
<span className="file-status-indicator">
{status.icon}
</span>
<span className="file-name">
{file.status === 'deleted' ? (
<del>{file.filename}</del>
) : (
file.filename
)}
</span>
{file.status === 'deleted' && (
<span className="deletion-notice">
This file was deleted
</span>
)}
</div>
{file.status === 'deleted' && (
<div className="deleted-file-content">
<p className="deletion-info">
{file.deletions} lines removed
</p>
<button onClick={() => viewDeletedContent(file)}>
View deleted content
</button>
</div>
)}
</div>
);
}Accessibility Considerations
function AccessibleFileStatus({ file }) {
const status = getFileStatus(file);
return (
<>
<span
className="file-status-icon"
role="img"
aria-label={status.label}
title={status.label}
>
{status.icon}
</span>
<span className="sr-only">
{status.label}: {file.filename}
</span>
</>
);
}Visual Examples
File List View:
┌─────────────────────────────────────────┐
│ ✨ src/newFeature.js +150 -0 │ ← Added (green)
│ 📝 src/existing.js +20 -15 │ ← Modified (yellow)
│ 🗑️ src/deprecated.js -0 -200 │ ← Deleted (red)
│ 📋 src/old.js → src/new.js +10 -5 │ ← Renamed (blue)
└─────────────────────────────────────────┘
Compact View:
[✨] newFile.js
[📝] modified.js
[🗑️] deleted.js (strikethrough)
[📋] renamed.js
Benefits
- Visual Clarity: Instantly see which files were deleted
- Consistency: Similar UX pattern to added files
- Improved Scanning: Easier to spot deleted files in long PR lists
- Accessibility: Clear indicators for all users
- Reduced Cognitive Load: No need to parse diff stats
Acceptance Criteria
- Deleted files show a distinctive icon
- Icon is visually consistent with added file icon style
- Deleted file names may have strikethrough styling
- Icon has proper accessibility labels
- Works in all file list views (tree view, flat view)
- Shows in PR file list
- Shows in diff headers
- Color scheme works in both light and dark themes
- Tooltip shows "Deleted" on hover
- Visual hierarchy is clear (added vs modified vs deleted)
Future Enhancements
- Animated transitions when files change status
- Filter to show only deleted files
- Bulk restore deleted files option
- Show deletion reason if available from commit message
🤖 Generated with Claude Code
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels