fix: improve DND drag feedback in EditableSchemaForm (#8449)

Three issues fixed:
- Dragged element clone was invisible because morphDraggedElementToBeLike
  ran before the clone was in the DOM, copying 0-height from the
  uninitialized ResizeTransitionWrapper shadow. Fixed with morphDisabled.
- Shadow placeholder was inconsistently hidden because the DND library's
  inline visibility:hidden was overwritten by RTW's reactive style binding.
  Fixed with !visible CSS class that overrides inline styles.
- Small cursor movements immediately triggered field reordering. Added a
  200ms grace period after drag start before processing reorder events.

The shadow element now shows a dashed blue drop-target indicator instead
of being fully hidden.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-03-19 09:15:37 +00:00
committed by GitHub
parent 7de98c0df4
commit fd7f0d3da9
2 changed files with 27 additions and 5 deletions
@@ -16,7 +16,11 @@
import ArgInput from './ArgInput.svelte'
import { createEventDispatcher, untrack } from 'svelte'
import { deepEqual } from 'fast-equals'
import { dragHandleZone, type Options as DndOptions } from '@windmill-labs/svelte-dnd-action'
import {
dragHandleZone,
SHADOW_ITEM_MARKER_PROPERTY_NAME,
type Options as DndOptions
} from '@windmill-labs/svelte-dnd-action'
import type { SchemaDiff } from '$lib/components/schema/schemaUtils.svelte'
import type { ComponentCustomCSS } from './apps/types'
import ResizeTransitionWrapper from './common/ResizeTransitionWrapper.svelte'
@@ -295,7 +299,9 @@
class={twMerge(
typeof diff[argName] === 'object' &&
diff[argName].diff !== 'same' &&
'bg-red-300 dark:bg-red-800 rounded-md'
'bg-red-300 dark:bg-red-800 rounded-md',
item[SHADOW_ITEM_MARKER_PROPERTY_NAME] &&
'!visible border-2 border-dashed border-blue-300 dark:border-blue-600 bg-blue-50 dark:bg-blue-900/20 rounded-md [&>*]:invisible'
)}
innerClass="w-full"
>
@@ -1,6 +1,6 @@
<script lang="ts">
import { createEventDispatcher, untrack } from 'svelte'
import { dragHandle } from '@windmill-labs/svelte-dnd-action'
import { dragHandle, TRIGGERS } from '@windmill-labs/svelte-dnd-action'
import SchemaForm from '../SchemaForm.svelte'
import { GripVertical } from 'lucide-svelte'
import type { Schema } from '$lib/common'
@@ -79,9 +79,24 @@
}
}
let dragStartTime = 0
const DRAG_GRACE_PERIOD_MS = 200
function handleConsider(e) {
dragDisabledState = false
const { items: newItems } = e.detail
const { items: newItems, info } = e.detail
if (info.trigger === TRIGGERS.DRAG_STARTED) {
dragStartTime = Date.now()
items = $state.snapshot(newItems)
return
}
// Ignore reorders during grace period so small movements don't cause jumps
if (Date.now() - dragStartTime < DRAG_GRACE_PERIOD_MS) {
return
}
items = $state.snapshot(newItems)
}
@@ -130,7 +145,8 @@
items,
flipDurationMs,
dropTargetStyle: {},
type: dndType
type: dndType,
morphDisabled: true
}}
{items}
{diff}