refactor(FileItem, FileList, FilesPage): enhance file selection UI and improve checkbox handling

- Added isSelected prop to FileItem for visual indication of selection.
- Updated FileList to manage selected file IDs and pass selection state to FileItem.
- Enhanced FilesPage checkbox handling with improved visibility on hover and selection state.
- Introduced CheckboxContainer for consistent styling of checkboxes across components.
This commit is contained in:
suyao 2025-06-13 19:20:16 +08:00
parent edeb9f84f9
commit 58f3edb352
No known key found for this signature in database
3 changed files with 58 additions and 10 deletions

View File

@ -29,6 +29,7 @@ interface FileItemProps {
}
style?: React.CSSProperties
gridTemplate?: string
isSelected?: boolean
}
const getFileIcon = (type?: string) => {
@ -79,13 +80,17 @@ const getFileIcon = (type?: string) => {
return <FileUnknownFilled />
}
const FileItem: React.FC<FileItemProps> = ({ fileInfo, style, gridTemplate = '' }) => {
const FileItem: React.FC<FileItemProps> = ({ fileInfo, style, gridTemplate = '', isSelected = false }) => {
const { name, ext, size, created_at, count, actions, icon, checkbox } = fileInfo
return (
<FileItemCard style={style}>
<FileItemCard style={style} className={isSelected ? 'selected' : ''}>
<FileGrid style={{ gridTemplateColumns: gridTemplate }}>
{checkbox && <FileCell>{checkbox}</FileCell>}
{checkbox && (
<FileCell>
<CheckboxContainer className="file-checkbox">{checkbox}</CheckboxContainer>
</FileCell>
)}
<FileCell>
<FileIcon>{icon || getFileIcon(ext)}</FileIcon>
</FileCell>
@ -116,11 +121,26 @@ const FileItemCard = styled.div`
box-shadow 0.2s ease,
background-color 0.2s ease;
--shadow-color: rgba(0, 0, 0, 0.05);
&:hover {
box-shadow:
0 10px 15px -3px var(--shadow-color),
0 4px 6px -4px var(--shadow-color);
}
.file-checkbox {
opacity: 0;
transition: opacity 0.2s ease;
}
&:hover .file-checkbox {
opacity: 1;
}
&.selected .file-checkbox {
opacity: 1;
}
body[theme-mode='dark'] & {
--shadow-color: rgba(255, 255, 255, 0.02);
}
@ -178,4 +198,10 @@ const FileCount = styled.div`
color: var(--color-text-2);
`
const CheckboxContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
`
export default memo(FileItem)

View File

@ -23,7 +23,7 @@ interface FileItemProps {
columnWidths?: string
}
const FileList: React.FC<FileItemProps> = ({ list, columnWidths }) => {
const FileList: React.FC<FileItemProps> = ({ list, columnWidths, selectedFileIds = [] }) => {
// if (id === FileTypes.IMAGE && files?.length && files?.length > 0) {
// return (
// <div style={{ padding: 16, overflowY: 'auto' }}>
@ -90,6 +90,7 @@ const FileList: React.FC<FileItemProps> = ({ list, columnWidths }) => {
actions: item.actions
}}
gridTemplate={columnWidths}
isSelected={selectedFileIds.includes(item.key as string)}
/>
</div>
)}

View File

@ -267,12 +267,14 @@ const FilesPage: FC = () => {
<TableHeader>
<TableGrid style={{ gridTemplateColumns: GRID_TEMPLATE }}>
<TableCell>
<Checkbox
indeterminate={selectedFileIds.length > 0 && selectedFileIds.length < sortedFiles.length}
checked={selectedFileIds.length === sortedFiles.length && sortedFiles.length > 0}
onChange={(e) => handleSelectAll(e.target.checked)}
disabled={sortedFiles.length === 0}
/>
<CheckboxContainer className={`header-checkbox ${selectedFileIds.length > 0 ? 'selected' : ''}`}>
<Checkbox
indeterminate={selectedFileIds.length > 0 && selectedFileIds.length < sortedFiles.length}
checked={selectedFileIds.length === sortedFiles.length && sortedFiles.length > 0}
onChange={(e) => handleSelectAll(e.target.checked)}
disabled={sortedFiles.length === 0}
/>
</CheckboxContainer>
</TableCell>
<TableCell>{/* 图标列 */}</TableCell>
<TableCell>
@ -471,6 +473,25 @@ const TableCell = styled.div`
const TableHeader = styled.div`
margin: 0 16px;
.header-checkbox {
opacity: 0;
transition: opacity 0.2s ease;
}
&:hover .header-checkbox {
opacity: 1;
}
.header-checkbox.selected {
opacity: 1;
}
`
const CheckboxContainer = styled.div`
display: flex;
align-items: center;
justify-content: center;
`
export default FilesPage