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 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
|
||||
|
||||
Reference in New Issue
Block a user