diff --git a/components/tour/__tests__/tour.test.tsx b/components/tour/__tests__/tour.test.tsx index 64bd27601..6c0b1de38 100644 --- a/components/tour/__tests__/tour.test.tsx +++ b/components/tour/__tests__/tour.test.tsx @@ -64,6 +64,11 @@ describe('tour targets', () => { expect(findTourTarget('[data-tour="one"]')?.id).toBe('tabbar'); }); + it('ignores a copy in a closed drawer', () => { + anchors('
'); + 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(''); render(); diff --git a/components/tour/tour-overlay.tsx b/components/tour/tour-overlay.tsx index 83f789252..8751bbc03 100644 --- a/components/tour/tour-overlay.tsx +++ b/components/tour/tour-overlay.tsx @@ -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; }