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