Skip to content

Commit 955cd9c

Browse files
committed
detecting non interactive overlay
1 parent d171c71 commit 955cd9c

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

worker/dyad-component-selector-client.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,56 @@
215215
}
216216
}
217217

218+
/**
219+
* Detects if an element is a non-interactive overlay (e.g. a gradient div
220+
* with absolute positioning covering its parent). When such an element is
221+
* the click target it blocks selection of the meaningful content underneath.
222+
* Returns the parent dyad-tagged element if the current one is an overlay,
223+
* or the element itself otherwise.
224+
*/
225+
function skipOverlayElement(el) {
226+
if (!el || !el.parentElement) return el;
227+
228+
// Never skip content-bearing elements
229+
const tag = el.tagName.toLowerCase();
230+
if (
231+
tag === "img" ||
232+
tag === "video" ||
233+
tag === "canvas" ||
234+
tag === "svg" ||
235+
tag === "iframe"
236+
) {
237+
return el;
238+
}
239+
240+
const style = getComputedStyle(el);
241+
242+
// Only consider absolutely/fixed positioned elements
243+
if (style.position !== "absolute" && style.position !== "fixed") return el;
244+
245+
// Don't skip scrollable containers (e.g. message lists with overflow-y-auto)
246+
if (style.overflowY === "auto" || style.overflowY === "scroll") return el;
247+
248+
// Must cover a large portion of its parent (inset-0 pattern)
249+
const parentRect = el.parentElement.getBoundingClientRect();
250+
const elRect = el.getBoundingClientRect();
251+
252+
if (parentRect.width === 0 || parentRect.height === 0) return el;
253+
254+
const widthRatio = elRect.width / parentRect.width;
255+
const heightRatio = elRect.height / parentRect.height;
256+
257+
// 98% accounts for sub-pixel rounding from borders/box-sizing while
258+
// being tight enough to only match true inset-0 overlays.
259+
if (widthRatio < 0.98 || heightRatio < 0.98) return el;
260+
261+
// This looks like an overlay — walk up to the parent with a dyad-id
262+
let parent = el.parentElement;
263+
while (parent && !parent.dataset.dyadId) parent = parent.parentElement;
264+
265+
return parent || el;
266+
}
267+
218268
// Helper function to check if mouse is over the toolbar
219269
function isMouseOverToolbar(mouseX, mouseY) {
220270
if (!componentCoordinates) return false;
@@ -328,6 +378,7 @@
328378

329379
let el = e.target;
330380
while (el && !el.dataset.dyadId) el = el.parentElement;
381+
if (el) el = skipOverlayElement(el);
331382

332383
const hoveredItem = overlays.find((item) => item.el === el);
333384

0 commit comments

Comments
 (0)