fix: drag & drop stability (#29730)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Michael Geers <michael@geers.tv>
This commit is contained in:
andig 2026-05-08 12:52:48 +02:00 • committed by GitHub
parent df955e7808
commit 1e8169683d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 25 deletions

View file

@ -8,12 +8,7 @@
:aria-label="$t('config.general.dragItem', { title })"
tabindex="0"
>
<div
class="drag-handle me-2"
:aria-label="$t('config.general.dragHandle')"
role="button"
tabindex="-1"
>
<div class="drag-handle me-2" aria-hidden="true">
<shopicon-regular-menu></shopicon-regular-menu>
</div>
<div class="flex-grow-1">
@ -42,7 +37,7 @@ export default defineComponent({
<style scoped>
.drag-drop-item {
cursor: move;
cursor: grab;
user-select: none;
background-color: var(--evcc-box);
border-color: var(--bs-border-color-translucent) !important;
@ -50,6 +45,10 @@ export default defineComponent({
transform: translate(0, 0);
}
.drag-drop-item:active {
cursor: grabbing;
}
.drag-drop-item--hidden {
opacity: 0.6;
}
@ -58,11 +57,11 @@ export default defineComponent({
color: var(--bs-secondary);
opacity: 0.7;
transition: opacity var(--evcc-transition-fast) ease-in-out;
cursor: grab;
cursor: inherit;
}
.drag-handle:active {
cursor: grabbing;
.drag-handle > * {
pointer-events: none;
}
.drag-drop-item:hover .drag-handle {

View file

@ -109,22 +109,17 @@ export async function dragElement(
sourceElement: Locator,
targetElement: Locator
): Promise<void> {
// Get bounding boxes to calculate actual positions
const sourceBox = await sourceElement.boundingBox();
// hover() waits for animations to settle before grabbing the source —
// avoids stale coordinates during the modal slide-in.
await sourceElement.hover();
await page.mouse.down();
const targetBox = await targetElement.boundingBox();
if (sourceBox && targetBox) {
// Move from center of source item to center of target item
const startX = sourceBox.x + sourceBox.width / 2;
const startY = sourceBox.y + sourceBox.height / 2;
const endX = targetBox.x + targetBox.width / 2;
const endY = targetBox.y + targetBox.height / 2;
await page.mouse.move(startX, startY);
await page.mouse.down();
await page.mouse.move(endX, endY, { steps: 10 });
await page.mouse.up();
}
if (!targetBox) throw new Error("dragElement: target has no bounding box");
await page.mouse.move(targetBox.x + targetBox.width / 2, targetBox.y + targetBox.height / 2, {
steps: 10,
});
await page.mouse.up();
}
export async function getDatalistOptions(input: Locator): Promise<string[]> {