From 741f521a1548b294cab3c4ac0470ad26ecaf43de Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Thu, 11 Jul 2024 15:57:13 +0200 Subject: [PATCH 01/11] Add option to remove overlay --- src/config.ts | 2 ++ src/driver.css | 2 +- src/driver.ts | 4 ++++ src/overlay.ts | 6 ++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index ed1ce772..3ef32fb9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,6 +8,7 @@ export type Config = { steps?: DriveStep[]; animate?: boolean; + overlayEnable?: boolean; overlayColor?: string; overlayOpacity?: number; smoothScroll?: boolean; @@ -55,6 +56,7 @@ export function configure(config: Config = {}) { animate: true, allowClose: true, overlayOpacity: 0.7, + overlayEnable: true, smoothScroll: false, disableActiveInteraction: false, showProgress: false, diff --git a/src/driver.css b/src/driver.css index 0128f76d..631943c8 100644 --- a/src/driver.css +++ b/src/driver.css @@ -2,7 +2,7 @@ pointer-events: none; } -.driver-active * { +.driver-active:not(.driver-no-overlay) * { pointer-events: none; } diff --git a/src/driver.ts b/src/driver.ts index 564f55b0..7ca81ab7 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -127,6 +127,10 @@ export function driver(options: Config = {}) { setState("isInitialized", true); document.body.classList.add("driver-active", getConfig("animate") ? "driver-fade" : "driver-simple"); + if(!getConfig("overlayEnable")){ + document.body.classList.add("driver-no-overlay"); + } + initEvents(); listen("overlayClick", handleClose); diff --git a/src/overlay.ts b/src/overlay.ts index cffb4e16..36da707d 100644 --- a/src/overlay.ts +++ b/src/overlay.ts @@ -55,6 +55,9 @@ export function trackActiveElement(element: Element) { } export function refreshOverlay() { + const isOverlayEnabled = getConfig('overlayEnable') + if (!isOverlayEnabled) return; + const activeStagePosition = getState("__activeStagePosition"); const overlaySvg = getState("__overlaySvg"); @@ -90,6 +93,9 @@ function mountOverlay(stagePosition: StageDefinition) { } function renderOverlay(stagePosition: StageDefinition) { + const isOverlayEnabled = getConfig('overlayEnable') + if (!isOverlayEnabled) return; + const overlaySvg = getState("__overlaySvg"); // TODO: cancel rendering if element is not visible From ffbe5050f9579b8996e40d75164775927e483b4e Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Thu, 11 Jul 2024 16:49:02 +0200 Subject: [PATCH 02/11] Close popup on click outside when overlay is disabled --- src/driver.ts | 1 + src/emitter.ts | 3 ++- src/events.ts | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/driver.ts b/src/driver.ts index 7ca81ab7..26acc90f 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -135,6 +135,7 @@ export function driver(options: Config = {}) { listen("overlayClick", handleClose); listen("escapePress", handleClose); + listen("windowClick", handleClose); listen("arrowLeftPress", handleArrowLeft); listen("arrowRightPress", handleArrowRight); } diff --git a/src/emitter.ts b/src/emitter.ts index 7964dfd7..7a514aa6 100644 --- a/src/emitter.ts +++ b/src/emitter.ts @@ -5,7 +5,8 @@ type allowedEvents = | "prevClick" | "closeClick" | "arrowRightPress" - | "arrowLeftPress"; + | "arrowLeftPress" + | "windowClick"; let registeredListeners: Partial<{ [key in allowedEvents]: () => void }> = {}; diff --git a/src/events.ts b/src/events.ts index ae643f71..7f7278a4 100644 --- a/src/events.ts +++ b/src/events.ts @@ -4,6 +4,16 @@ import { getState, setState } from "./state"; import { getConfig } from "./config"; import { getFocusableElements } from "./utils"; +function onWindowClick(e: MouseEvent) { + const isPopoverContent = (e.target as HTMLElement)?.closest('#driver-popover-content') + const isActive = getState('activeStep') + const isTransitioning = getState("__transitionCallback") + + if (isTransitioning || !isActive || isPopoverContent) return; + + emit('windowClick') +} + export function requireRefresh() { const resizeTimeout = getState("__resizeTimeout"); if (resizeTimeout) { @@ -118,10 +128,14 @@ export function initEvents() { window.addEventListener("keydown", trapFocus, false); window.addEventListener("resize", requireRefresh); window.addEventListener("scroll", requireRefresh); + if (!getConfig('overlayEnable')) { + window.addEventListener('click', onWindowClick) + } } export function destroyEvents() { window.removeEventListener("keyup", onKeyup); window.removeEventListener("resize", requireRefresh); window.removeEventListener("scroll", requireRefresh); + window.removeEventListener("click", onWindowClick); } From 7fd1726411501ac38b431bf99d58d93757b6d3c6 Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 10:42:20 +0200 Subject: [PATCH 03/11] Add option to disable popover sticking to viewport --- index.html | 26 ++++++++++++++++++++++++++ src/config.ts | 2 ++ src/driver.css | 4 ++-- src/driver.ts | 2 +- src/events.ts | 3 +++ src/popover.ts | 27 +++++++++++++++++---------- 6 files changed, 51 insertions(+), 13 deletions(-) diff --git a/index.html b/index.html index 6a35359d..4e54a209 100644 --- a/index.html +++ b/index.html @@ -177,6 +177,8 @@

Highlight Feature

+ + @@ -877,6 +879,30 @@

Usage and Demo

}); }); + document.getElementById("backdrop-disabled-btn").addEventListener("click", () => { + driver({ + overlayEnable: false, + }).highlight({ + element: "h2", + popover: { + title: "MIT License", + description: "A lightweight, no-dependency JavaScript engine to drive user's focus.", + side: "bottom", + align: "start", + }, + });; + }); + + document.getElementById("disabled-stick-to-viewport").addEventListener("click", () => { + const driverObj = driver({ + popoverStickToViewport: false, + overlayEnable: false, + steps: basicTourSteps + }); + + driverObj.drive(); + }); + document.getElementById("activate-check-btn").addEventListener("click", () => { const driverObj = driver({ showButtons: false, diff --git a/src/config.ts b/src/config.ts index 3ef32fb9..13f270fc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -23,6 +23,7 @@ export type Config = { // Popover specific configuration popoverClass?: string; popoverOffset?: number; + popoverStickToViewport?: boolean; showButtons?: AllowedButtons[]; disableButtons?: AllowedButtons[]; showProgress?: boolean; @@ -63,6 +64,7 @@ export function configure(config: Config = {}) { stagePadding: 10, stageRadius: 5, popoverOffset: 10, + popoverStickToViewport: true, showButtons: ["next", "previous", "close"], disableButtons: [], overlayColor: "#000", diff --git a/src/driver.css b/src/driver.css index 631943c8..16a08718 100644 --- a/src/driver.css +++ b/src/driver.css @@ -8,8 +8,8 @@ .driver-active .driver-active-element, .driver-active .driver-active-element *, -.driver-popover, -.driver-popover * { +.driver-active .driver-popover, +.driver-active .driver-popover * { pointer-events: auto; } diff --git a/src/driver.ts b/src/driver.ts index 26acc90f..c2d4914d 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -8,7 +8,7 @@ import { getState, resetState, setState } from "./state"; import "./driver.css"; export type DriveStep = { - element?: string | Element; + element?: string | Element | (() => Element); onHighlightStarted?: DriverHook; onHighlighted?: DriverHook; onDeselected?: DriverHook; diff --git a/src/events.ts b/src/events.ts index 7f7278a4..17a60061 100644 --- a/src/events.ts +++ b/src/events.ts @@ -5,6 +5,9 @@ import { getConfig } from "./config"; import { getFocusableElements } from "./utils"; function onWindowClick(e: MouseEvent) { + const isOverlayEnabled = getConfig('overlayEnable') + if (isOverlayEnabled) return; + const isPopoverContent = (e.target as HTMLElement)?.closest('#driver-popover-content') const isActive = getState('activeStep') const isTransitioning = getState("__transitionCallback") diff --git a/src/popover.ts b/src/popover.ts index a11ca97c..3fd3d671 100644 --- a/src/popover.ts +++ b/src/popover.ts @@ -268,6 +268,8 @@ function calculateTopForLeftRight( } ): number { const { elementDimensions, popoverDimensions, popoverPadding, popoverArrowDimensions } = config; + const shouldStickToViewport = getConfig('popoverStickToViewport'); + const safeZone = shouldStickToViewport ? popoverArrowDimensions.width : Number.MIN_SAFE_INTEGER if (alignment === "start") { return Math.max( @@ -275,7 +277,7 @@ function calculateTopForLeftRight( elementDimensions.top - popoverPadding, window.innerHeight - popoverDimensions!.realHeight - popoverArrowDimensions.width ), - popoverArrowDimensions.width + safeZone ); } @@ -285,7 +287,7 @@ function calculateTopForLeftRight( elementDimensions.top - popoverDimensions?.realHeight + elementDimensions.height + popoverPadding, window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width ), - popoverArrowDimensions.width + safeZone ); } @@ -295,7 +297,7 @@ function calculateTopForLeftRight( elementDimensions.top + elementDimensions.height / 2 - popoverDimensions?.realHeight / 2, window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width ), - popoverArrowDimensions.width + safeZone ); } @@ -313,6 +315,8 @@ function calculateLeftForTopBottom( } ): number { const { elementDimensions, popoverDimensions, popoverPadding, popoverArrowDimensions } = config; + const shouldStickToViewport = getConfig('popoverStickToViewport'); + const safeZone = shouldStickToViewport ? popoverArrowDimensions.width : Number.MIN_SAFE_INTEGER if (alignment === "start") { return Math.max( @@ -320,7 +324,7 @@ function calculateLeftForTopBottom( elementDimensions.left - popoverPadding, window.innerWidth - popoverDimensions!.realWidth - popoverArrowDimensions.width ), - popoverArrowDimensions.width + safeZone ); } @@ -330,7 +334,7 @@ function calculateLeftForTopBottom( elementDimensions.left - popoverDimensions?.realWidth + elementDimensions.width + popoverPadding, window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width ), - popoverArrowDimensions.width + safeZone ); } @@ -340,7 +344,7 @@ function calculateLeftForTopBottom( elementDimensions.left + elementDimensions.width / 2 - popoverDimensions?.realWidth / 2, window.innerWidth - popoverDimensions?.realWidth - popoverArrowDimensions.width ), - popoverArrowDimensions.width + safeZone ); } @@ -379,6 +383,8 @@ export function repositionPopover(element: Element, step: DriveStep) { const noneOptimal = !isTopOptimal && !isBottomOptimal && !isLeftOptimal && !isRightOptimal; let popoverRenderedSide: Side = requiredSide; + const shouldStickToViewport = getConfig('popoverStickToViewport'); + if (requiredSide === "top" && isTopOptimal) { isRightOptimal = isLeftOptimal = isBottomOptimal = false; } else if (requiredSide === "bottom" && isBottomOptimal) { @@ -443,10 +449,11 @@ export function repositionPopover(element: Element, step: DriveStep) { popoverRenderedSide = "right"; } else if (isTopOptimal) { - const topToSet = Math.min( + const topToSet = shouldStickToViewport ? Math.min( topValue, window.innerHeight - popoverDimensions!.realHeight - popoverArrowDimensions.width - ); + ) : topValue; + let leftToSet = calculateLeftForTopBottom(requiredAlignment, { elementDimensions, popoverDimensions, @@ -461,10 +468,10 @@ export function repositionPopover(element: Element, step: DriveStep) { popoverRenderedSide = "top"; } else if (isBottomOptimal) { - const bottomToSet = Math.min( + const bottomToSet = shouldStickToViewport ? Math.min( bottomValue, window.innerHeight - popoverDimensions?.realHeight - popoverArrowDimensions.width - ); + ) : bottomValue; let leftToSet = calculateLeftForTopBottom(requiredAlignment, { elementDimensions, From 5d1ec417a9de44c18bc595872c6a406541e08b56 Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 10:42:27 +0200 Subject: [PATCH 04/11] Allow to pass function which returns Element as step element config --- src/highlight.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/highlight.ts b/src/highlight.ts index 961a26af..6b4463e6 100644 --- a/src/highlight.ts +++ b/src/highlight.ts @@ -27,9 +27,22 @@ function mountDummyElement(): Element { return element; } -export function highlight(step: DriveStep) { +function getStepElement(step: DriveStep): Element | null { const { element } = step; - let elemObj = typeof element === "string" ? document.querySelector(element) : element; + + if (typeof element === 'function') { + return element(); + } + + if (typeof element === 'string') { + return document.querySelector(element); + } + + return element ?? null; +} + +export function highlight(step: DriveStep) { + let elemObj = getStepElement(step); // If the element is not found, we mount a 1px div // at the center of the screen to highlight and show From 2d48c134db3efc2fc303fd289dedc96c8fd8f4aa Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 11:21:23 +0200 Subject: [PATCH 05/11] Add option to lock body scrolling --- index.html | 13 +++++++++++-- src/config.ts | 2 ++ src/driver.css | 4 ++++ src/driver.ts | 6 +++++- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 4e54a209..e924ffca 100644 --- a/index.html +++ b/index.html @@ -179,6 +179,7 @@

Highlight Feature

+ @@ -896,8 +897,16 @@

Usage and Demo

document.getElementById("disabled-stick-to-viewport").addEventListener("click", () => { const driverObj = driver({ popoverStickToViewport: false, - overlayEnable: false, - steps: basicTourSteps + steps: basicTourSteps, + }); + + driverObj.drive(); + }); + + document.getElementById("disabled-scroll").addEventListener("click", () => { + const driverObj = driver({ + allowScroll: false, + steps: basicTourSteps, }); driverObj.drive(); diff --git a/src/config.ts b/src/config.ts index 13f270fc..b0b94578 100644 --- a/src/config.ts +++ b/src/config.ts @@ -13,6 +13,7 @@ export type Config = { overlayOpacity?: number; smoothScroll?: boolean; allowClose?: boolean; + allowScroll?: boolean; stagePadding?: number; stageRadius?: number; @@ -56,6 +57,7 @@ export function configure(config: Config = {}) { currentConfig = { animate: true, allowClose: true, + allowScroll: true, overlayOpacity: 0.7, overlayEnable: true, smoothScroll: false, diff --git a/src/driver.css b/src/driver.css index 16a08718..3f8f10a7 100644 --- a/src/driver.css +++ b/src/driver.css @@ -2,6 +2,10 @@ pointer-events: none; } +.driver-active.driver-no-scroll { + overflow: hidden; +} + .driver-active:not(.driver-no-overlay) * { pointer-events: none; } diff --git a/src/driver.ts b/src/driver.ts index c2d4914d..0007a27d 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -127,10 +127,14 @@ export function driver(options: Config = {}) { setState("isInitialized", true); document.body.classList.add("driver-active", getConfig("animate") ? "driver-fade" : "driver-simple"); - if(!getConfig("overlayEnable")){ + if (!getConfig("overlayEnable")) { document.body.classList.add("driver-no-overlay"); } + if (!getConfig("allowScroll")) { + document.body.classList.add("driver-no-scroll"); + } + initEvents(); listen("overlayClick", handleClose); From be29918ef80e982595898fd0b74b733b2b9dfd62 Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 13:50:38 +0200 Subject: [PATCH 06/11] Add option to disable popup animation between the same elements --- index.html | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ src/config.ts | 2 ++ src/driver.css | 2 +- src/highlight.ts | 10 ++++-- src/popover.ts | 6 +++- 5 files changed, 97 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index e924ffca..b82aa130 100644 --- a/index.html +++ b/index.html @@ -180,6 +180,7 @@

Highlight Feature

+ @@ -412,6 +413,77 @@

Usage and Demo

}, ]; + + const sameElementSteps = [ + { + element: ".page-header h1", + popover: { + title: "1 popup on the same element", + description: + "Unlike the older version, new version doesn't work with z-indexes so no more positional issues.", + side: "left", + align: "start", + }, + }, + { + element: ".page-header h1", + popover: { + title: "2 popup on the same element", + description: + "Unlike the older version, new version doesn't work with z-indexes so no more positional issues.", + side: "left", + align: "start", + }, + }, + { + element: ".page-header h1", + popover: { + title: "3 popup on the same element", + description: + "Unlike the older version, new version doesn't work with z-indexes so no more positional issues.", + side: "left", + align: "start", + }, + }, + { + element: ".page-header sup", + popover: { + title: "Improved Hooks", + description: + "Unlike the older version, new version doesn't work with z-indexes so no more positional issues.", + side: "bottom", + align: "start", + }, + }, + { + popover: { + title: "No Element", + description: "You can now have popovers without elements as well", + }, + }, + { + element: '.buttons', + popover: { + title: "Buttons", + description: "Here are some buttons", + }, + }, + { + element: "#scrollable-area", + popover: { + title: "Scrollable Areas", + description: "There are no issues with scrollable element tours as well.", + }, + }, + { + element: "#third-scroll-paragraph", + popover: { + title: "Nested Scrolls", + description: "Even the nested scrollable elements work now.", + }, + }, + ]; + document.getElementById("non-animated-tour").addEventListener("click", () => { const driverObj = driver({ animate: false, @@ -912,6 +984,16 @@

Usage and Demo

driverObj.drive(); }); + document.getElementById("disabled-same-element-animation").addEventListener("click", () => { + const driverObj = driver({ + allowScroll: false, + animateBetweenSameElements: false, + steps: sameElementSteps, + }); + + driverObj.drive(); + }); + document.getElementById("activate-check-btn").addEventListener("click", () => { const driverObj = driver({ showButtons: false, diff --git a/src/config.ts b/src/config.ts index b0b94578..a12f1f85 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,6 +8,7 @@ export type Config = { steps?: DriveStep[]; animate?: boolean; + animateBetweenSameElements?: boolean overlayEnable?: boolean; overlayColor?: string; overlayOpacity?: number; @@ -56,6 +57,7 @@ let currentConfig: Config = {}; export function configure(config: Config = {}) { currentConfig = { animate: true, + animateBetweenSameElements: true, allowClose: true, allowScroll: true, overlayOpacity: 0.7, diff --git a/src/driver.css b/src/driver.css index 3f8f10a7..f47fb149 100644 --- a/src/driver.css +++ b/src/driver.css @@ -31,7 +31,7 @@ animation: animate-fade-in 200ms ease-in-out; } -.driver-fade .driver-popover { +.driver-fade .driver-popover:not(.driver-no-animation) { animation: animate-fade-in 200ms; } diff --git a/src/highlight.ts b/src/highlight.ts index 6b4463e6..0941d28f 100644 --- a/src/highlight.ts +++ b/src/highlight.ts @@ -75,11 +75,12 @@ function transferHighlight(toElement: Element, toStep: DriveStep) { const fromStep = getState("__activeStep"); const fromElement = getState("__activeElement") || toElement; + const isSameElement = fromElement === toElement; // If it's the first time we're highlighting an element, we show // the popover immediately. Otherwise, we wait for the animation // to finish before showing the popover. - const isFirstHighlight = !fromElement || fromElement === toElement; + const isFirstHighlight = !fromElement || isSameElement; const isToDummyElement = toElement.id === "driver-dummy-element"; const isFromDummyElement = fromElement.id === "driver-dummy-element"; @@ -115,6 +116,8 @@ function transferHighlight(toElement: Element, toStep: DriveStep) { setState("activeStep", toStep); setState("activeElement", toElement); + const isSameElementAnimationEnabled = !isSameElement || !!getConfig("animateBetweenSameElements"); + const animate = () => { const transitionCallback = getState("__transitionCallback"); @@ -129,8 +132,9 @@ function transferHighlight(toElement: Element, toStep: DriveStep) { const timeRemaining = duration - elapsed; const isHalfwayThrough = timeRemaining <= duration / 2; + if (toStep.popover && isHalfwayThrough && !isPopoverRendered && hasDelayedPopover) { - renderPopover(toElement, toStep); + renderPopover(toElement, toStep, isSameElementAnimationEnabled); isPopoverRendered = true; } @@ -162,7 +166,7 @@ function transferHighlight(toElement: Element, toStep: DriveStep) { bringInView(toElement); if (!hasDelayedPopover && toStep.popover) { - renderPopover(toElement, toStep); + renderPopover(toElement, toStep, isSameElementAnimationEnabled); } fromElement.classList.remove("driver-active-element", "driver-no-interaction"); diff --git a/src/popover.ts b/src/popover.ts index 3fd3d671..f51163eb 100644 --- a/src/popover.ts +++ b/src/popover.ts @@ -58,7 +58,7 @@ export function hidePopover() { popover.wrapper.style.display = "none"; } -export function renderPopover(element: Element, step: DriveStep) { +export function renderPopover(element: Element, step: DriveStep, isAnimationEnabled: boolean = true) { let popover = getState("popover"); if (popover) { document.body.removeChild(popover.wrapper); @@ -151,6 +151,10 @@ export function renderPopover(element: Element, step: DriveStep) { const customPopoverClass = step.popover?.popoverClass || getConfig("popoverClass") || ""; popoverWrapper.className = `driver-popover ${customPopoverClass}`.trim(); + if (!isAnimationEnabled) { + popoverWrapper.classList.add("driver-no-animation"); + } + // Handles the popover button clicks onDriverClick( popover.wrapper, From b11d4e22c811cd464ed51937a0a298e6acfa31cc Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 14:13:09 +0200 Subject: [PATCH 07/11] Fix wrong activeElement when running requireRefresh function on scroll --- index.html | 1 - src/highlight.ts | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index b82aa130..7987adc1 100644 --- a/index.html +++ b/index.html @@ -986,7 +986,6 @@

Usage and Demo

document.getElementById("disabled-same-element-animation").addEventListener("click", () => { const driverObj = driver({ - allowScroll: false, animateBetweenSameElements: false, steps: sameElementSteps, }); diff --git a/src/highlight.ts b/src/highlight.ts index 0941d28f..78273555 100644 --- a/src/highlight.ts +++ b/src/highlight.ts @@ -128,6 +128,8 @@ function transferHighlight(toElement: Element, toStep: DriveStep) { return; } + setState("__activeElement", toElement); + const elapsed = Date.now() - start; const timeRemaining = duration - elapsed; const isHalfwayThrough = timeRemaining <= duration / 2; @@ -154,7 +156,6 @@ function transferHighlight(toElement: Element, toStep: DriveStep) { setState("__previousStep", fromStep); setState("__previousElement", fromElement); setState("__activeStep", toStep); - setState("__activeElement", toElement); } window.requestAnimationFrame(animate); From 8e7a044a0c962434fac520480bb9818bf535a9bf Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 15:16:45 +0200 Subject: [PATCH 08/11] Add body classes on highlight to allow config setting on the fly --- src/driver.ts | 10 +--------- src/highlight.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/driver.ts b/src/driver.ts index 0007a27d..a1024408 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -127,14 +127,6 @@ export function driver(options: Config = {}) { setState("isInitialized", true); document.body.classList.add("driver-active", getConfig("animate") ? "driver-fade" : "driver-simple"); - if (!getConfig("overlayEnable")) { - document.body.classList.add("driver-no-overlay"); - } - - if (!getConfig("allowScroll")) { - document.body.classList.add("driver-no-scroll"); - } - initEvents(); listen("overlayClick", handleClose); @@ -243,7 +235,7 @@ export function driver(options: Config = {}) { const onDeselected = activeStep?.onDeselected || getConfig("onDeselected"); const onDestroyed = getConfig("onDestroyed"); - document.body.classList.remove("driver-active", "driver-fade", "driver-simple"); + document.body.classList.remove("driver-active", "driver-fade", "driver-simple", "driver-no-overlay", "driver-no-scroll"); destroyEvents(); destroyPopover(); diff --git a/src/highlight.ts b/src/highlight.ts index 78273555..f3057517 100644 --- a/src/highlight.ts +++ b/src/highlight.ts @@ -44,6 +44,14 @@ function getStepElement(step: DriveStep): Element | null { export function highlight(step: DriveStep) { let elemObj = getStepElement(step); + if (!getConfig("overlayEnable")) { + document.body.classList.add("driver-no-overlay"); + } + + if (!getConfig("allowScroll")) { + document.body.classList.add("driver-no-scroll"); + } + // If the element is not found, we mount a 1px div // at the center of the screen to highlight and show // the popover on top of that. This is to show a From c86bf598f432cbc482752ad3296f2661f436103b Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 19:55:17 +0200 Subject: [PATCH 09/11] Do not scroll to popover (we already scroll to element) --- src/popover.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/popover.ts b/src/popover.ts index f51163eb..0228c622 100644 --- a/src/popover.ts +++ b/src/popover.ts @@ -225,7 +225,6 @@ export function renderPopover(element: Element, step: DriveStep, isAnimationEnab } repositionPopover(element, step); - bringInView(popoverWrapper); // Focus on the first focusable element in active element or popover const isToDummyElement = element.classList.contains("driver-dummy-element"); From 3720f49769fc4b9607d2572d836b22c7702e6e48 Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 20:31:09 +0200 Subject: [PATCH 10/11] Fix types --- src/driver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver.ts b/src/driver.ts index a1024408..2aeab45c 100644 --- a/src/driver.ts +++ b/src/driver.ts @@ -8,7 +8,7 @@ import { getState, resetState, setState } from "./state"; import "./driver.css"; export type DriveStep = { - element?: string | Element | (() => Element); + element?: string | Element | (() => Element | null); onHighlightStarted?: DriverHook; onHighlighted?: DriverHook; onDeselected?: DriverHook; From 977f917a1718b1dd68b169bc97d5008e9fffc55a Mon Sep 17 00:00:00 2001 From: Kamil Beda Date: Mon, 15 Jul 2024 20:57:36 +0200 Subject: [PATCH 11/11] Remove unused import --- src/popover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/popover.ts b/src/popover.ts index 0228c622..ccd45395 100644 --- a/src/popover.ts +++ b/src/popover.ts @@ -1,4 +1,4 @@ -import { bringInView, getFocusableElements } from "./utils"; +import { getFocusableElements } from "./utils"; import { Config, DriverHook, getConfig } from "./config"; import { getState, setState, State } from "./state"; import { DriveStep } from "./driver";