From 78882b1d4d11e06f27a04260d13a84cc8be9a833 Mon Sep 17 00:00:00 2001 From: hhhjin Date: Sun, 12 Apr 2026 19:38:52 +0900 Subject: [PATCH] fix: preserve explorer drag overlay sizing --- .../src/components/dnd/dnd-provider.tsx | 1 + .../dnd/explorer-drag-overlay.test.tsx | 40 ++++++++++++++++++- .../components/dnd/explorer-drag-overlay.tsx | 38 +++++++++++++++++- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/apps/desktop/src/components/dnd/dnd-provider.tsx b/apps/desktop/src/components/dnd/dnd-provider.tsx index 9b4ec9c7..b38352b7 100644 --- a/apps/desktop/src/components/dnd/dnd-provider.tsx +++ b/apps/desktop/src/components/dnd/dnd-provider.tsx @@ -66,6 +66,7 @@ function renderDragOverlay(source: DragOverlaySource) { ) } diff --git a/apps/desktop/src/components/dnd/explorer-drag-overlay.test.tsx b/apps/desktop/src/components/dnd/explorer-drag-overlay.test.tsx index 6cdf6700..0cadefac 100644 --- a/apps/desktop/src/components/dnd/explorer-drag-overlay.test.tsx +++ b/apps/desktop/src/components/dnd/explorer-drag-overlay.test.tsx @@ -1,5 +1,8 @@ import { describe, expect, it } from "vitest" -import { getExplorerDragOverlayName } from "./explorer-drag-overlay" +import { + getExplorerDragOverlayName, + getExplorerDragOverlayStyle, +} from "./explorer-drag-overlay" describe("getExplorerDragOverlayName", () => { it("prefers the display name when present", () => { @@ -21,3 +24,38 @@ describe("getExplorerDragOverlayName", () => { ).toBe("folder") }) }) + +describe("getExplorerDragOverlayStyle", () => { + it("returns undefined when no source element is available", () => { + expect(getExplorerDragOverlayStyle()).toBeUndefined() + }) + + it("preserves the source row width and padding", () => { + const sourceElement = { + getBoundingClientRect: () => + ({ + width: 240, + }) as DOMRect, + ownerDocument: { + defaultView: { + getComputedStyle: () => ({ + boxSizing: "border-box", + paddingTop: "2px", + paddingRight: "8px", + paddingBottom: "2px", + paddingLeft: "36px", + }), + }, + }, + } as unknown as Element + + expect(getExplorerDragOverlayStyle(sourceElement)).toEqual({ + boxSizing: "border-box", + paddingTop: "2px", + paddingRight: "8px", + paddingBottom: "2px", + paddingLeft: "36px", + width: "240px", + }) + }) +}) diff --git a/apps/desktop/src/components/dnd/explorer-drag-overlay.tsx b/apps/desktop/src/components/dnd/explorer-drag-overlay.tsx index 04b52ec9..f4c9a06d 100644 --- a/apps/desktop/src/components/dnd/explorer-drag-overlay.tsx +++ b/apps/desktop/src/components/dnd/explorer-drag-overlay.tsx @@ -1,19 +1,47 @@ import { cn } from "@mdit/ui/lib/utils" import { ChevronRight } from "lucide-react" +import { type CSSProperties, useMemo } from "react" import type { FileEntryDragData } from "./dnd-types" type ExplorerDragOverlayProps = { name: string isDirectory: boolean + sourceElement?: Element | null } export function getExplorerDragOverlayName(data: FileEntryDragData): string { return data.displayName ?? data.name ?? "" } +export function getExplorerDragOverlayStyle( + sourceElement?: Element | null, +): CSSProperties | undefined { + if (!sourceElement || !("getBoundingClientRect" in sourceElement)) { + return undefined + } + + const ownerWindow = sourceElement.ownerDocument?.defaultView + if (!ownerWindow?.getComputedStyle) { + return undefined + } + + const rect = sourceElement.getBoundingClientRect() + const computedStyle = ownerWindow.getComputedStyle(sourceElement) + + return { + boxSizing: + (computedStyle.boxSizing as CSSProperties["boxSizing"]) || "border-box", + paddingTop: computedStyle.paddingTop, + paddingRight: computedStyle.paddingRight, + paddingBottom: computedStyle.paddingBottom, + paddingLeft: computedStyle.paddingLeft, + width: rect.width > 0 ? `${rect.width}px` : undefined, + } +} + function getExplorerDragOverlayClassName(isDirectory: boolean) { return cn( - "pointer-events-none flex min-w-0 max-w-80 items-center gap-1 rounded-sm bg-transparent px-0 py-0 text-sm text-accent-foreground/95 shadow-none ring-0 outline-none border-0", + "pointer-events-none flex min-w-0 max-w-none items-center gap-1 rounded-sm bg-transparent px-0 py-0 text-sm text-accent-foreground/95 shadow-none ring-0 outline-none border-0", isDirectory ? "pr-2" : "pr-1", ) } @@ -21,9 +49,15 @@ function getExplorerDragOverlayClassName(isDirectory: boolean) { export function ExplorerDragOverlay({ name, isDirectory, + sourceElement, }: ExplorerDragOverlayProps) { + const style = useMemo( + () => getExplorerDragOverlayStyle(sourceElement), + [sourceElement], + ) + return ( -
+
{isDirectory ? (