fix: compression UI — proper before/after display with folds tokens

Always shows Original size pill even before checkbox is checked.
After checking: shows 'compressing...' then reveals Compressed pill
with exact size and percentage saved. Green tint on compressed pill
when >5% saving; neutral when minimal gain.

Replaced all var(--bg-*) / var(--tc-*) CSS vars with folds
color.Surface.* and color.SurfaceVariant.* tokens so the UI renders
correctly in all themes. Blob cleanup is automatic — the compressed
Blob is referenced only during upload and GC'd with the upload atom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 12:37:11 -04:00
parent c6760b0ba4
commit d3dcf93f1a
@@ -117,7 +117,6 @@ function CompressionCheckbox({ fileItem, metadata, setMetadata }: CompressionChe
return;
}
// Optimistically mark as enabled; kick off compression in background
setMetadata(fileItem, { ...metadata, compressImage: true, compressionResult: undefined });
setCompressing(true);
@@ -136,63 +135,108 @@ function CompressionCheckbox({ fileItem, metadata, setMetadata }: CompressionChe
? Math.round(((result.originalSize - result.compressedSize) / result.originalSize) * 100)
: null;
const originalSize = formatFileSize(originalFile.size);
return (
<Box
direction="Column"
gap="100"
gap="200"
style={{
marginTop: '4px',
padding: '6px 8px',
background: 'var(--bg-surface-low)',
borderRadius: '6px',
border: '1px solid var(--bg-surface-border)',
fontSize: '0.8rem',
marginTop: config.space.S100,
padding: `${config.space.S200} ${config.space.S300}`,
background: color.SurfaceVariant.Container,
borderRadius: config.radii.R300,
border: `1px solid ${color.SurfaceVariant.ContainerLine}`,
}}
>
{/* Checkbox row */}
<Box alignItems="Center" gap="200">
<input
id={`compress-${originalFile.name}-${originalFile.size}`}
type="checkbox"
checked={checked}
onChange={handleChange}
style={{ cursor: 'pointer', accentColor: 'var(--bg-secondary)' }}
style={{ cursor: 'pointer', flexShrink: 0 }}
/>
<label
htmlFor={`compress-${originalFile.name}-${originalFile.size}`}
style={{ cursor: 'pointer', color: 'var(--text-primary)', userSelect: 'none' }}
style={{
cursor: 'pointer',
color: color.SurfaceVariant.OnContainer,
userSelect: 'none',
fontSize: '0.8rem',
}}
>
Compress before uploading
</label>
{compressing && (
<Text size="T200" style={{ color: 'var(--text-secondary)', marginLeft: '4px' }}>
estimating
<Text size="T200" style={{ opacity: 0.6, marginLeft: 'auto' }}>
compressing
</Text>
)}
</Box>
{checked && !compressing && result !== undefined && (
<Text
size="T200"
{/* Before / after row — always show original; show compressed when ready */}
<Box gap="200" alignItems="Center" wrap="Wrap">
<Box
gap="100"
alignItems="Center"
style={{
color: result
? savingPct !== null && savingPct > 0
? 'var(--tc-success-normal, #2e7d32)'
: 'var(--text-secondary)'
: 'var(--tc-danger-normal)',
paddingLeft: '20px',
padding: `2px ${config.space.S200}`,
borderRadius: config.radii.R300,
background: color.Surface.Container,
border: `1px solid ${color.Surface.ContainerLine}`,
}}
>
{result
? savingPct !== null && savingPct > 0
? `→ ~${formatFileSize(result.compressedSize)} (${savingPct}% smaller)`
: `${formatFileSize(result.compressedSize)} (no significant saving)`
: 'Compression not available for this file'}
</Text>
)}
{checked && !compressing && result === undefined && (
<Text size="T200" style={{ color: 'var(--text-secondary)', paddingLeft: '20px' }}>
Original: {formatFileSize(originalFile.size)}
</Text>
)}
<Text size="T200" style={{ opacity: 0.6 }}>
Original
</Text>
<Text size="T200" style={{ fontWeight: 600 }}>
{originalSize}
</Text>
</Box>
{checked && !compressing && result !== undefined && (
<>
<Text size="T200" style={{ opacity: 0.5 }}>
</Text>
<Box
gap="100"
alignItems="Center"
style={{
padding: `2px ${config.space.S200}`,
borderRadius: config.radii.R300,
background:
savingPct !== null && savingPct > 5
? (color.Success?.Container ?? color.Primary.Container)
: color.Surface.Container,
border: `1px solid ${
savingPct !== null && savingPct > 5
? (color.Success?.ContainerLine ?? color.Primary.ContainerLine)
: color.Surface.ContainerLine
}`,
}}
>
<Text size="T200" style={{ opacity: 0.6 }}>
Compressed
</Text>
{result ? (
<Text size="T200" style={{ fontWeight: 600 }}>
{formatFileSize(result.compressedSize)}
{savingPct !== null && savingPct > 0 && (
<span style={{ opacity: 0.7, marginLeft: 4 }}>({savingPct}% smaller)</span>
)}
</Text>
) : (
<Text size="T200" style={{ opacity: 0.6 }}>
unavailable
</Text>
)}
</Box>
</>
)}
</Box>
</Box>
);
}