fix: track active bar element correctly for drag calculations

Fixed issue where dragged bars weren't updating visually because a single
barRef was shared across all bars. Now each bar passes its element reference
to the drag handlers, allowing proper width calculations during drag.

Changes:
- Renamed barRef to activeBarRef for clarity
- Updated handleMouseDown/handleTouchStart to accept bar element parameter
- Pass e.currentTarget as bar element in onMouseDown/onTouchStart handlers
- Clear activeBarRef on drag end (mouseup/touchend)

This fixes the visual feedback - bars now correctly resize as you drag them.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-08 10:42:47 +01:00
parent 2c621f2c8e
commit bc71768d6a

View File

@@ -18,7 +18,7 @@ export default function VisualComparison({
const [draggingUnit, setDraggingUnit] = useState<string | null>(null);
const dragStartX = useRef<number>(0);
const dragStartWidth = useRef<number>(0);
const barRef = useRef<HTMLDivElement>(null);
const activeBarRef = useRef<HTMLDivElement | null>(null);
// Calculate percentages for visual bars using logarithmic scale
const withPercentages = useMemo(() => {
if (conversions.length === 0) return [];
@@ -80,19 +80,20 @@ export default function VisualComparison({
}, []);
// Mouse drag handlers
const handleMouseDown = useCallback((e: React.MouseEvent, unit: string, currentPercentage: number) => {
const handleMouseDown = useCallback((e: React.MouseEvent, unit: string, currentPercentage: number, barElement: HTMLDivElement) => {
if (!onValueChange) return;
e.preventDefault();
setDraggingUnit(unit);
dragStartX.current = e.clientX;
dragStartWidth.current = currentPercentage;
activeBarRef.current = barElement;
}, [onValueChange]);
const handleMouseMove = useCallback((e: MouseEvent) => {
if (!draggingUnit || !barRef.current || !onValueChange) return;
if (!draggingUnit || !activeBarRef.current || !onValueChange) return;
const barWidth = barRef.current.offsetWidth;
const barWidth = activeBarRef.current.offsetWidth;
const deltaX = e.clientX - dragStartX.current;
const deltaPercentage = (deltaX / barWidth) * 100;
@@ -116,24 +117,26 @@ export default function VisualComparison({
const handleMouseUp = useCallback(() => {
setDraggingUnit(null);
activeBarRef.current = null;
}, []);
// Touch drag handlers
const handleTouchStart = useCallback((e: React.TouchEvent, unit: string, currentPercentage: number) => {
const handleTouchStart = useCallback((e: React.TouchEvent, unit: string, currentPercentage: number, barElement: HTMLDivElement) => {
if (!onValueChange) return;
const touch = e.touches[0];
setDraggingUnit(unit);
dragStartX.current = touch.clientX;
dragStartWidth.current = currentPercentage;
activeBarRef.current = barElement;
}, [onValueChange]);
const handleTouchMove = useCallback((e: TouchEvent) => {
if (!draggingUnit || !barRef.current || !onValueChange) return;
if (!draggingUnit || !activeBarRef.current || !onValueChange) return;
e.preventDefault(); // Prevent scrolling while dragging
const touch = e.touches[0];
const barWidth = barRef.current.offsetWidth;
const barWidth = activeBarRef.current.offsetWidth;
const deltaX = touch.clientX - dragStartX.current;
const deltaPercentage = (deltaX / barWidth) * 100;
@@ -154,6 +157,7 @@ export default function VisualComparison({
const handleTouchEnd = useCallback(() => {
setDraggingUnit(null);
activeBarRef.current = null;
}, []);
// Add/remove global event listeners for drag
@@ -202,15 +206,22 @@ export default function VisualComparison({
</div>
{/* Progress bar */}
<div
ref={barRef}
className={cn(
"w-full h-8 bg-muted rounded-lg overflow-hidden border border-border relative",
"transition-all duration-200",
isDraggable && "cursor-grab active:cursor-grabbing",
isDragging && "ring-2 ring-ring ring-offset-2 ring-offset-background scale-105"
)}
onMouseDown={(e) => isDraggable && handleMouseDown(e, item.unit, item.percentage)}
onTouchStart={(e) => isDraggable && handleTouchStart(e, item.unit, item.percentage)}
onMouseDown={(e) => {
if (isDraggable && e.currentTarget instanceof HTMLDivElement) {
handleMouseDown(e, item.unit, item.percentage, e.currentTarget);
}
}}
onTouchStart={(e) => {
if (isDraggable && e.currentTarget instanceof HTMLDivElement) {
handleTouchStart(e, item.unit, item.percentage, e.currentTarget);
}
}}
>
{/* Colored fill */}
<div