fix: skip tour steps whose target sits in a closed drawer on the phone

This commit is contained in:
Linus Rath
2026-10-28 04:29:50 +01:00
parent 9b9cc4ca33
commit b865569ce2
2 changed files with 11 additions and 2 deletions
+5
View File
@@ -64,6 +64,11 @@ describe('tour targets', () => {
expect(findTourTarget('[data-tour="one"]')?.id).toBe('tabbar');
});
it('ignores a copy in a closed drawer', () => {
anchors('<div inert><a data-tour="one" id="drawer" data-size></a></div>');
expect(findTourTarget('[data-tour="one"]')).toBeNull();
});
it('skips a step whose target is in the page but not shown, instead of leaving the user behind the overlay', () => {
anchors('<a data-tour="one"></a>');
render(<TourOverlay />);
+6 -2
View File
@@ -24,12 +24,16 @@ const TOOLTIP_MAX_W = 360;
/**
* The first element for the selector that is on screen. The same anchor can
* exist twice (the rail and the phone's tab bar); one with no size is not
* rendered in this layout and has nothing to point at.
* rendered in this layout, and one in a closed drawer (inert, or pushed off
* the side of the screen) can't be seen: neither has anything to point at.
*/
export function findTourTarget(selector: string): Element | null {
for (const el of document.querySelectorAll(selector)) {
if (el.closest("[inert]")) continue;
const r = el.getBoundingClientRect();
if (r.width > 0 || r.height > 0) return el;
if (r.width === 0 && r.height === 0) continue;
if (r.right <= 0 || r.left >= window.innerWidth) continue;
return el;
}
return null;
}