-
-
Notifications
You must be signed in to change notification settings - Fork 1
[BUG] Splitter ResizeTrigger drag offset issue - Panel doesn't follow cursor #95
Description
Description
When dragging the ResizeTrigger in the Splitter component, the panel doesn't follow the cursor position accurately. There's a noticeable "jump" or offset that makes the drag interaction feel unresponsive and not following the user's hand movement (不跟手).
Root Cause
After investigating the source code, I found the issue in packages/components/splitter/src/machine.ts.
Current implementation:
const offset = pointValue - before.endThis calculates the offset based on the absolute pointer position relative to the panel boundary, rather than the relative movement from where the drag started.
// Store initial cursor position when drag starts
initialCursorPosition = cursorPosition
// Calculate delta based on relative movement
const offsetPixels = cursorPosition - initialCursorPosition
const offsetPercentage = (offsetPixels / groupSizeInPixels) * 100Steps to Reproduce
- Create a basic Splitter layout with two panels
- Click anywhere on the ResizeTrigger (not exactly at the panel boundary)
- Start dragging
- Observe that the panel "jumps" to align with the cursor position instead of moving relative to where you started dragging
Expected Behavior
When the user clicks on the ResizeTrigger and starts dragging:
- The initial click position should be recorded
- Panel size changes should be calculated based on how far the cursor has moved from the initial position
- The panel should smoothly follow the cursor without any initial "jump"
Actual Behavior
- The panel jumps to align with the absolute cursor position
- If you click on the left side of a wide ResizeTrigger, the panel boundary jumps to that position
- The drag feels "disconnected" from the cursor movement
Suggested Fix
In machine.ts, the dragging state initialization should store the initial cursor position:
// When entering dragging state
entry: ['focusResizeHandle', 'storeInitialCursorPosition'],
// New action
storeInitialCursorPosition: (ctx, evt) => {
ctx.initialCursorPosition = evt.point
ctx.initialPanelSizes = {
before: ctx.previousPanels.before.size,
after: ctx.previousPanels.after.size,
}
}Then in setPointerValue, calculate the delta relative to the initial position:
setPointerValue: (ctx, evt) => {
const rootEl = dom.getRootEl(ctx)
const rootSize = ctx.orientation === 'horizontal' ? rootEl.offsetWidth : rootEl.offsetHeight
// Calculate relative delta
const currentPosition = getRelativePoint(evt.point, rootEl)
const initialPosition = getRelativePoint(ctx.initialCursorPosition, rootEl)
const deltaPercent = ((currentPosition - initialPosition) / rootSize) * 100
// Apply delta to initial sizes
const newBeforeSize = ctx.initialPanelSizes.before + deltaPercent
const newAfterSize = ctx.initialPanelSizes.after - deltaPercent
// ... apply constraints and update
}