From ce2a8d88f9eec52b68ec43a5b19ca8ca7beaf8b7 Mon Sep 17 00:00:00 2001 From: Eric Gullickson <16152721+ericgullickson@users.noreply.github.com> Date: Fri, 6 Feb 2026 20:55:08 -0600 Subject: [PATCH] fix: Mobile image crop fix --- .../components/CameraCapture/CropTool.tsx | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/frontend/src/shared/components/CameraCapture/CropTool.tsx b/frontend/src/shared/components/CameraCapture/CropTool.tsx index 1d3a750..09f8b54 100644 --- a/frontend/src/shared/components/CameraCapture/CropTool.tsx +++ b/frontend/src/shared/components/CameraCapture/CropTool.tsx @@ -3,7 +3,7 @@ * @ai-context Allows user to adjust crop area with touch/mouse, confirm or retake */ -import React, { useCallback, useState } from 'react'; +import React, { useCallback, useState, useRef, useEffect } from 'react'; import { Box, IconButton, Button, Typography, CircularProgress } from '@mui/material'; import CheckIcon from '@mui/icons-material/Check'; import RefreshIcon from '@mui/icons-material/Refresh'; @@ -22,12 +22,28 @@ export const CropTool: React.FC = ({ onSkip, }) => { const [isProcessing, setIsProcessing] = useState(false); + const imageAreaRef = useRef(null); + const [imageMaxHeight, setImageMaxHeight] = useState(0); const { cropArea, isDragging, resetCrop, executeCrop, handleDragStart } = useImageCrop({ aspectRatio: lockAspectRatio ? aspectRatio : undefined, }); + // Measure available height for the image so the crop container + // matches the rendered image exactly (fixes mobile crop offset) + useEffect(() => { + const updateMaxHeight = () => { + if (imageAreaRef.current) { + const rect = imageAreaRef.current.getBoundingClientRect(); + setImageMaxHeight(rect.height - 32); // subtract p:2 padding (16px * 2) + } + }; + updateMaxHeight(); + window.addEventListener('resize', updateMaxHeight); + return () => window.removeEventListener('resize', updateMaxHeight); + }, []); + const handleConfirm = useCallback(async () => { setIsProcessing(true); try { @@ -61,6 +77,7 @@ export const CropTool: React.FC = ({ > {/* Image with crop overlay */} = ({ data-crop-container sx={{ position: 'relative', - maxWidth: '100%', - maxHeight: '100%', userSelect: 'none', touchAction: isDragging ? 'none' : 'auto', }} @@ -87,7 +102,7 @@ export const CropTool: React.FC = ({ alt="Captured" style={{ maxWidth: '100%', - maxHeight: '100%', + maxHeight: imageMaxHeight > 0 ? `${imageMaxHeight}px` : '70vh', display: 'block', }} draggable={false}