Files
CodePilot/src/components/layout/ResizeHandle.tsx
T
7418andClaude Opus 4.6 b1e6b0bfac fix: 修复预览面板拖拽分隔线快速移动时宽度不跟手的问题
根因:ResizeHandle 使用 document.addEventListener('mousemove') 监听拖拽,
当鼠标快速移到 iframe(HTML 预览)上方时,iframe 捕获了鼠标事件,
document 上的 mousemove 回调不再触发,导致宽度停止更新。

修复:将 mouse events 替换为 pointer events + setPointerCapture。
- onMouseDown → onPointerDown + setPointerCapture
- 在元素上直接监听 onPointerMove/onPointerUp(不再挂 document 事件)
- pointer capture 确保所有后续事件锁定到拖拽手柄,即使鼠标移到 iframe 上方
- 添加 touch-none CSS 防止触屏浏览器默认行为干扰拖拽
- 代码更简洁:不再需要手动 addEventListener/removeEventListener

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 15:49:01 +08:00

65 lines
1.8 KiB
TypeScript

"use client";
import { useCallback, useRef } from "react";
import { cn } from "@/lib/utils";
interface ResizeHandleProps {
side: "left" | "right";
onResize: (delta: number) => void;
onResizeEnd?: () => void;
}
export function ResizeHandle({ side, onResize, onResizeEnd }: ResizeHandleProps) {
const isDragging = useRef(false);
const startX = useRef(0);
const handlePointerDown = useCallback(
(e: React.PointerEvent) => {
e.preventDefault();
isDragging.current = true;
startX.current = e.clientX;
// Capture pointer so all subsequent events route here, even over iframes
(e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
document.body.style.cursor = "col-resize";
document.body.style.userSelect = "none";
},
[]
);
const handlePointerMove = useCallback(
(e: React.PointerEvent) => {
if (!isDragging.current) return;
const delta = e.clientX - startX.current;
startX.current = e.clientX;
onResize(delta);
},
[onResize]
);
const handlePointerUp = useCallback(
(e: React.PointerEvent) => {
if (!isDragging.current) return;
isDragging.current = false;
(e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId);
document.body.style.cursor = "";
document.body.style.userSelect = "";
onResizeEnd?.();
},
[onResizeEnd]
);
return (
<div
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
onPointerUp={handlePointerUp}
className={cn(
"group relative z-10 flex w-1 shrink-0 cursor-col-resize items-center justify-center touch-none",
side === "left" ? "-ml-0.5" : "-mr-0.5"
)}
>
<div className="h-full w-px bg-transparent transition-colors duration-150 group-hover:bg-border" />
</div>
);
}