Improve filepreview

This commit is contained in:
Connor Yoh 2025-08-06 13:37:02 +01:00
parent fcf7fcd9a3
commit c650f07a70
3 changed files with 66 additions and 53 deletions

View File

@ -12,7 +12,7 @@ interface CompactFileDetailsProps {
thumbnail: string | null; thumbnail: string | null;
selectedFiles: FileWithUrl[]; selectedFiles: FileWithUrl[];
currentFileIndex: number; currentFileIndex: number;
hasMultipleFiles: boolean; numberOfFiles: number;
isAnimating: boolean; isAnimating: boolean;
onPrevious: () => void; onPrevious: () => void;
onNext: () => void; onNext: () => void;
@ -24,7 +24,7 @@ const CompactFileDetails: React.FC<CompactFileDetailsProps> = ({
thumbnail, thumbnail,
selectedFiles, selectedFiles,
currentFileIndex, currentFileIndex,
hasMultipleFiles, numberOfFiles,
isAnimating, isAnimating,
onPrevious, onPrevious,
onNext, onNext,
@ -32,6 +32,7 @@ const CompactFileDetails: React.FC<CompactFileDetailsProps> = ({
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const hasSelection = selectedFiles.length > 0; const hasSelection = selectedFiles.length > 0;
const hasMultipleFiles = numberOfFiles > 1;
return ( return (
<Stack gap="xs" style={{ height: '100%' }}> <Stack gap="xs" style={{ height: '100%' }}>

View File

@ -64,7 +64,7 @@ const FileDetails: React.FC<FileDetailsProps> = ({
thumbnail={getCurrentThumbnail()} thumbnail={getCurrentThumbnail()}
selectedFiles={selectedFiles} selectedFiles={selectedFiles}
currentFileIndex={currentFileIndex} currentFileIndex={currentFileIndex}
hasMultipleFiles={hasMultipleFiles} numberOfFiles={selectedFiles.length}
isAnimating={isAnimating} isAnimating={isAnimating}
onPrevious={handlePrevious} onPrevious={handlePrevious}
onNext={handleNext} onNext={handleNext}
@ -79,7 +79,7 @@ const FileDetails: React.FC<FileDetailsProps> = ({
<FilePreview <FilePreview
currentFile={currentFile} currentFile={currentFile}
thumbnail={getCurrentThumbnail()} thumbnail={getCurrentThumbnail()}
hasMultipleFiles={hasMultipleFiles} numberOfFiles={selectedFiles.length}
isAnimating={isAnimating} isAnimating={isAnimating}
modalHeight={modalHeight} modalHeight={modalHeight}
onPrevious={handlePrevious} onPrevious={handlePrevious}

View File

@ -8,7 +8,7 @@ import { FileWithUrl } from '../../types/file';
interface FilePreviewProps { interface FilePreviewProps {
currentFile: FileWithUrl | null; currentFile: FileWithUrl | null;
thumbnail: string | null; thumbnail: string | null;
hasMultipleFiles: boolean; numberOfFiles: number;
isAnimating: boolean; isAnimating: boolean;
modalHeight: string; modalHeight: string;
onPrevious: () => void; onPrevious: () => void;
@ -18,12 +18,39 @@ interface FilePreviewProps {
const FilePreview: React.FC<FilePreviewProps> = ({ const FilePreview: React.FC<FilePreviewProps> = ({
currentFile, currentFile,
thumbnail, thumbnail,
hasMultipleFiles, numberOfFiles,
isAnimating, isAnimating,
modalHeight, modalHeight,
onPrevious, onPrevious,
onNext onNext
}) => { }) => {
const hasMultipleFiles = numberOfFiles > 1;
// Common style objects
const navigationArrowStyle = {
position: 'absolute' as const,
top: '50%',
transform: 'translateY(-50%)',
zIndex: 10
};
const stackDocumentBaseStyle = {
position: 'absolute' as const,
width: '100%',
height: '100%'
};
const animationStyle = {
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
transform: isAnimating ? 'scale(0.95) translateX(1.25rem)' : 'scale(1) translateX(0)',
opacity: isAnimating ? 0.7 : 1
};
const mainDocumentShadow = '0 6px 16px rgba(0, 0, 0, 0.2)';
const stackDocumentShadows = {
back: '0 2px 8px rgba(0, 0, 0, 0.1)',
middle: '0 3px 10px rgba(0, 0, 0, 0.12)'
};
return ( return (
<Box p="xs" style={{ textAlign: 'center', flexShrink: 0 }}> <Box p="xs" style={{ textAlign: 'center', flexShrink: 0 }}>
<Box style={{ position: 'relative', width: "100%", height: `calc(${modalHeight} * 0.5 - 2rem)`, margin: '0 auto', display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <Box style={{ position: 'relative', width: "100%", height: `calc(${modalHeight} * 0.5 - 2rem)`, margin: '0 auto', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
@ -36,11 +63,8 @@ const FilePreview: React.FC<FilePreviewProps> = ({
color="blue" color="blue"
disabled={isAnimating} disabled={isAnimating}
style={{ style={{
position: 'absolute', ...navigationArrowStyle,
left: '0', left: '0'
top: '50%',
transform: 'translateY(-50%)',
zIndex: 10
}} }}
> >
<ChevronLeftIcon /> <ChevronLeftIcon />
@ -50,34 +74,30 @@ const FilePreview: React.FC<FilePreviewProps> = ({
{/* Document Stack Container */} {/* Document Stack Container */}
<Box style={{ position: 'relative', width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <Box style={{ position: 'relative', width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
{/* Background documents (stack effect) */} {/* Background documents (stack effect) */}
{hasMultipleFiles && ( {/* Show 2 shadow pages for 3+ files */}
<> {numberOfFiles >= 3 && (
{/* Third document (furthest back) */} <Box
<Box style={{
style={{ ...stackDocumentBaseStyle,
position: 'absolute', backgroundColor: 'var(--mantine-color-gray-3)',
width: '100%', boxShadow: stackDocumentShadows.back,
height: '100%', transform: 'translate(0.75rem, 0.75rem) rotate(2deg)',
backgroundColor: 'var(--mantine-color-gray-2)', zIndex: 1
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)', }}
transform: 'translate(0.75rem, 0.75rem) rotate(2deg)', />
zIndex: 1 )}
}}
/>
{/* Second document */} {/* Show 1 shadow page for 2+ files */}
<Box {numberOfFiles >= 2 && (
style={{ <Box
position: 'absolute', style={{
width: '100%', ...stackDocumentBaseStyle,
height: '100%', backgroundColor: 'var(--mantine-color-gray-2)',
backgroundColor: 'var(--mantine-color-gray-1)', boxShadow: stackDocumentShadows.middle,
boxShadow: '0 3px 10px rgba(0, 0, 0, 0.12)', transform: 'translate(0.375rem, 0.375rem) rotate(1deg)',
transform: 'translate(0.375rem, 0.375rem) rotate(1deg)', zIndex: 2
zIndex: 2 }}
}} />
/>
</>
)} )}
{/* Main document */} {/* Main document */}
@ -91,13 +111,10 @@ const FilePreview: React.FC<FilePreviewProps> = ({
maxHeight: '100%', maxHeight: '100%',
width: 'auto', width: 'auto',
height: 'auto', height: 'auto',
boxShadow: '0 6px 16px rgba(0, 0, 0, 0.2)', boxShadow: mainDocumentShadow,
borderRadius: '0.5rem',
position: 'relative', position: 'relative',
zIndex: 3, zIndex: 3,
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', ...animationStyle
transform: isAnimating ? 'scale(0.95) translateX(1.25rem)' : 'scale(1) translateX(0)',
opacity: isAnimating ? 0.7 : 1
}} }}
/> />
) : currentFile ? ( ) : currentFile ? (
@ -105,12 +122,10 @@ const FilePreview: React.FC<FilePreviewProps> = ({
width: '80%', width: '80%',
height: '80%', height: '80%',
backgroundColor: 'var(--mantine-color-gray-1)', backgroundColor: 'var(--mantine-color-gray-1)',
boxShadow: '0 6px 16px rgba(0, 0, 0, 0.2)', boxShadow: mainDocumentShadow,
position: 'relative', position: 'relative',
zIndex: 3, zIndex: 3,
transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)', ...animationStyle
transform: isAnimating ? 'scale(0.95) translateX(1.25rem)' : 'scale(1) translateX(0)',
opacity: isAnimating ? 0.7 : 1
}}> }}>
<PictureAsPdfIcon style={{ fontSize: '3rem', color: 'var(--mantine-color-gray-6)' }} /> <PictureAsPdfIcon style={{ fontSize: '3rem', color: 'var(--mantine-color-gray-6)' }} />
</Center> </Center>
@ -126,11 +141,8 @@ const FilePreview: React.FC<FilePreviewProps> = ({
color="blue" color="blue"
disabled={isAnimating} disabled={isAnimating}
style={{ style={{
position: 'absolute', ...navigationArrowStyle,
right: '0', right: '0'
top: '50%',
transform: 'translateY(-50%)',
zIndex: 10
}} }}
> >
<ChevronRightIcon /> <ChevronRightIcon />