mirror of
https://github.com/kamranahmedse/driver.js.git
synced 2026-10-30 19:27:40 +08:00
Add allowScroll config to lock body scroll during tour
This commit is contained in:
@@ -36,6 +36,9 @@ type Config = {
|
||||
smoothScroll?: boolean;
|
||||
// Whether to allow closing the popover by clicking on the backdrop. (default: true)
|
||||
allowClose?: boolean;
|
||||
// Whether to allow scrolling the page while the driver is active.
|
||||
// Set to false to lock body scrolling for the duration of the tour. (default: true)
|
||||
allowScroll?: boolean;
|
||||
// Opacity of the backdrop. (default: 0.5)
|
||||
overlayOpacity?: number;
|
||||
// What to do when the overlay backdrop is clicked.
|
||||
|
||||
@@ -5,6 +5,7 @@ import { arrowGroup } from "./arrow";
|
||||
import { tourGroup } from "./tour";
|
||||
import { apiGroup } from "./api";
|
||||
import { durationGroup } from "./duration";
|
||||
import { scrollGroup } from "./scroll";
|
||||
|
||||
export const exampleGroups: ExampleGroup[] = [
|
||||
highlightGroup,
|
||||
@@ -12,6 +13,7 @@ export const exampleGroups: ExampleGroup[] = [
|
||||
arrowGroup,
|
||||
tourGroup,
|
||||
durationGroup,
|
||||
scrollGroup,
|
||||
apiGroup,
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { driver } from "driver.js";
|
||||
import type { ExampleGroup } from "./types";
|
||||
import { basicTourSteps } from "./shared";
|
||||
|
||||
// Both examples run the same tour; only `allowScroll` differs so the page's
|
||||
// scrollability during the tour can be compared directly.
|
||||
function tourWithScroll(allowScroll: boolean) {
|
||||
driver({
|
||||
allowScroll,
|
||||
showProgress: true,
|
||||
showButtons: ["next", "previous", "close"],
|
||||
steps: basicTourSteps,
|
||||
}).drive();
|
||||
}
|
||||
|
||||
export const scrollGroup: ExampleGroup = {
|
||||
title: "Body Scrolling (test)",
|
||||
examples: [
|
||||
{
|
||||
id: "scroll-allowed",
|
||||
title: "Scroll Allowed (default)",
|
||||
description: "LOOK: while the tour is active you can still scroll the page with the wheel or trackpad.",
|
||||
run() {
|
||||
tourWithScroll(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "scroll-locked",
|
||||
title: "Scroll Locked",
|
||||
description: "LOOK: with allowScroll:false the body is frozen — wheel and trackpad scrolling do nothing.",
|
||||
run() {
|
||||
tourWithScroll(false);
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -17,6 +17,7 @@ export type Config = {
|
||||
overlayOpacity?: number;
|
||||
smoothScroll?: boolean;
|
||||
allowClose?: boolean;
|
||||
allowScroll?: boolean;
|
||||
overlayClickBehavior?: "close" | "nextStep" | DriverHook;
|
||||
stagePadding?: number;
|
||||
stageRadius?: number;
|
||||
@@ -63,6 +64,7 @@ export function configure(config: Config = {}) {
|
||||
animate: true,
|
||||
duration: 400,
|
||||
allowClose: true,
|
||||
allowScroll: true,
|
||||
overlayClickBehavior: "close",
|
||||
overlayOpacity: 0.7,
|
||||
smoothScroll: false,
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.driver-active.driver-no-scroll {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.driver-active * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
+4
-1
@@ -222,6 +222,9 @@ export function driver(options: Config = {}): Driver {
|
||||
|
||||
setState("isInitialized", true);
|
||||
document.body.classList.add("driver-active", getConfig("animate") ? "driver-fade" : "driver-simple");
|
||||
if (!getConfig("allowScroll")) {
|
||||
document.body.classList.add("driver-no-scroll");
|
||||
}
|
||||
document.body.style.setProperty("--driver-animation-duration", `${getConfig("duration") || 400}ms`);
|
||||
|
||||
initEvents();
|
||||
@@ -332,7 +335,7 @@ export function driver(options: Config = {}): Driver {
|
||||
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-scroll");
|
||||
document.body.style.removeProperty("--driver-animation-duration");
|
||||
|
||||
destroyEvents();
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createDriver, SAMPLE_STEPS, useDriverHarness } from "./utils";
|
||||
|
||||
useDriverHarness();
|
||||
|
||||
const hasNoScroll = () => document.body.classList.contains("driver-no-scroll");
|
||||
|
||||
describe("allowScroll", () => {
|
||||
it("allows body scrolling by default", () => {
|
||||
const d = createDriver({ animate: false });
|
||||
d.highlight({ element: "#intro", popover: { title: "Intro" } });
|
||||
|
||||
expect(d.getConfig().allowScroll).toBe(true);
|
||||
expect(hasNoScroll()).toBe(false);
|
||||
});
|
||||
|
||||
it("locks body scrolling when allowScroll is false", () => {
|
||||
const d = createDriver({ animate: false, allowScroll: false });
|
||||
d.highlight({ element: "#intro", popover: { title: "Intro" } });
|
||||
|
||||
expect(hasNoScroll()).toBe(true);
|
||||
});
|
||||
|
||||
it("locks body scrolling for a tour when allowScroll is false", () => {
|
||||
const d = createDriver({ animate: false, allowScroll: false, steps: SAMPLE_STEPS });
|
||||
d.drive();
|
||||
|
||||
expect(hasNoScroll()).toBe(true);
|
||||
});
|
||||
|
||||
it("releases the scroll lock on destroy", () => {
|
||||
const d = createDriver({ animate: false, allowScroll: false });
|
||||
d.highlight({ element: "#intro", popover: { title: "Intro" } });
|
||||
d.destroy();
|
||||
|
||||
expect(hasNoScroll()).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user