fix: drag & drop — fix overlay position and root drop zone

- Use top positioning instead of transform for virtual items (fixes
  DragOverlay appearing at top instead of near cursor)
- Add spacer at bottom of tree for root drop target
- Highlight root drop zone during drag
This commit is contained in:
iliya 2026-03-01 13:28:54 +02:00
parent 02bf87b0b0
commit d7c9e87c40

View file

@ -344,7 +344,11 @@ export const EditorFileTree = ({
onDragCancel={handleDragCancel} onDragCancel={handleDragCancel}
autoScroll={{ threshold: { x: 0, y: 0.15 } }} autoScroll={{ threshold: { x: 0, y: 0.15 } }}
> >
<RootDropZone ref={scrollRef} projectPath={projectPath}> <RootDropZone
ref={scrollRef}
projectPath={projectPath}
isDropTarget={dropTargetPath === projectPath}
>
<div <div
style={{ style={{
height: `${virtualizer.getTotalSize()}px`, height: `${virtualizer.getTotalSize()}px`,
@ -365,16 +369,19 @@ export const EditorFileTree = ({
onClick={handleNodeClick} onClick={handleNodeClick}
style={{ style={{
position: 'absolute', position: 'absolute',
top: 0, top: `${virtualItem.start}px`,
left: 0, left: 0,
width: '100%', width: '100%',
height: `${virtualItem.size}px`, height: `${virtualItem.size}px`,
transform: `translateY(${virtualItem.start}px)`,
}} }}
/> />
); );
})} })}
</div> </div>
{/* Spacer at bottom — drop here to move to project root */}
{draggedItem && (
<div className="h-16 w-full shrink-0" aria-label="Drop here for project root" />
)}
</RootDropZone> </RootDropZone>
<DragOverlay dropAnimation={null}> <DragOverlay dropAnimation={null}>
{draggedItem && <DragOverlayFileItem item={draggedItem} />} {draggedItem && <DragOverlayFileItem item={draggedItem} />}
@ -398,8 +405,8 @@ export const EditorFileTree = ({
const RootDropZone = React.forwardRef< const RootDropZone = React.forwardRef<
HTMLDivElement, HTMLDivElement,
{ projectPath: string | null; children: React.ReactNode } { projectPath: string | null; isDropTarget: boolean; children: React.ReactNode }
>(({ projectPath, children }, ref) => { >(({ projectPath, isDropTarget, children }, ref) => {
const { setNodeRef } = useDroppable({ const { setNodeRef } = useDroppable({
id: 'root-drop-zone', id: 'root-drop-zone',
data: { isRoot: true, path: projectPath }, data: { isRoot: true, path: projectPath },
@ -417,7 +424,13 @@ const RootDropZone = React.forwardRef<
); );
return ( return (
<div ref={combinedRef} className="h-full overflow-y-auto" role="tree"> <div
ref={combinedRef}
className={`h-full overflow-y-auto transition-colors ${
isDropTarget ? 'bg-blue-400/5 ring-1 ring-inset ring-blue-400/30' : ''
}`}
role="tree"
>
{children} {children}
</div> </div>
); );