diff --git a/workspaces/e2e/tests/modal-overlay/modal-overlay.html b/workspaces/e2e/tests/modal-overlay/modal-overlay.html new file mode 100644 index 0000000..453f5a0 --- /dev/null +++ b/workspaces/e2e/tests/modal-overlay/modal-overlay.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/workspaces/e2e/tests/modal-overlay/modal-overlay.spec.ts b/workspaces/e2e/tests/modal-overlay/modal-overlay.spec.ts new file mode 100644 index 0000000..0246522 --- /dev/null +++ b/workspaces/e2e/tests/modal-overlay/modal-overlay.spec.ts @@ -0,0 +1,21 @@ +import { expect, test } from "@playwright/test"; + +test("should show overlay without close on click by default", async ({ page }) => { + await page.goto("/modal-overlay/modal-overlay.html"); + await expect(page.locator(".flows-modal")).toBeVisible(); + await page.locator(".flows-modal-overlay").click({ position: { x: 100, y: 100 } }); + await expect(page.locator(".flows-modal")).toBeVisible(); +}); + +test("should close overlay on click", async ({ page }) => { + await page.goto("/modal-overlay/modal-overlay.html?closeOnOverlayClick=true"); + await expect(page.locator(".flows-modal")).toBeVisible(); + await page.locator(".flows-modal-overlay").click({ position: { x: 100, y: 100 } }); + await expect(page.locator(".flows-modal")).toBeHidden(); +}); + +test("should hide overlay", async ({ page }) => { + await page.goto("/modal-overlay/modal-overlay.html?hideOverlay=true"); + await expect(page.locator(".flows-modal")).toBeVisible(); + await expect(page.locator(".flows-modal-overlay")).toBeHidden(); +}); diff --git a/workspaces/e2e/tests/modal-overlay/modal-overlay.ts b/workspaces/e2e/tests/modal-overlay/modal-overlay.ts new file mode 100644 index 0000000..4707fb5 --- /dev/null +++ b/workspaces/e2e/tests/modal-overlay/modal-overlay.ts @@ -0,0 +1,24 @@ +import { init } from "@flows/js/core"; + +const closeOnOverlayClick = + new URLSearchParams(window.location.search).get("closeOnOverlayClick") === "true"; +const hideOverlay = new URLSearchParams(window.location.search).get("hideOverlay") === "true"; + +init({ + flows: [ + { + id: "flow", + location: "/", + steps: [ + { + title: "Hello", + body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + hideOverlay, + closeOnOverlayClick, + }, + ], + }, + ], +}); + +document.querySelector("button")?.addEventListener("click", () => console.log("Hello!")); diff --git a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.html b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.html index e2584de..d3e8224 100644 --- a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.html +++ b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.html @@ -11,8 +11,8 @@

Tooltip overlay

-
- +
+
diff --git a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts index a966ffb..160fad5 100644 --- a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts +++ b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts @@ -15,3 +15,8 @@ test("should close overlay on click", async ({ page }) => { await page.locator(".flows-tooltip-overlay-click-layer").click(); await expect(page.locator(".flows-tooltip")).not.toBeVisible(); }); + +test("should match screenshot", async ({ page }) => { + await page.goto("/tooltip-overlay/tooltip-overlay.html"); + await expect(page).toHaveScreenshot({ scale: "css" }); +}); diff --git a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-chromium-linux.png b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-chromium-linux.png new file mode 100644 index 0000000..309e5e9 Binary files /dev/null and b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-chromium-linux.png differ diff --git a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-firefox-linux.png b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-firefox-linux.png new file mode 100644 index 0000000..244474f Binary files /dev/null and b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-firefox-linux.png differ diff --git a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-webkit-linux.png b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-webkit-linux.png new file mode 100644 index 0000000..257aefd Binary files /dev/null and b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.spec.ts-snapshots/should-match-screenshot-1-webkit-linux.png differ diff --git a/workspaces/js/css/template.css b/workspaces/js/css/template.css index b5ee2b8..010360e 100644 --- a/workspaces/js/css/template.css +++ b/workspaces/js/css/template.css @@ -186,19 +186,21 @@ /* Modal styles */ .flows-modal-overlay { + position: fixed; + inset: 0; background-color: var(--flows-modal-overlayBackground); +} +.flows-modal-wrapper { position: fixed; - top: 0; - left: 0; - width: 100%; - height: 100%; + inset: 0; display: grid; place-items: center; padding: var(--flows-modal-padding); overflow: auto; + pointer-events: none; } - .flows-modal { + pointer-events: auto; background-color: var(--flows-bg-default); border: var(--flows-border); color: var(--flows-fg-default); diff --git a/workspaces/js/src/core/render.tsx b/workspaces/js/src/core/render.tsx index cfb803f..1e2c4bd 100644 --- a/workspaces/js/src/core/render.tsx +++ b/workspaces/js/src/core/render.tsx @@ -206,7 +206,7 @@ const renderTooltip = ({ const overlayClickLayer = (
); root.appendChild(overlayClickLayer); @@ -252,7 +252,7 @@ const renderModal = ({ state: FlowState; }): void => { const modal = ( -
+
{getStepHeader({ step })} {step.body && ( @@ -262,6 +262,13 @@ const renderModal = ({
); + if (!step.hideOverlay) { + root.appendChild( +
, + ); + } root.appendChild(modal); }; diff --git a/workspaces/js/src/core/validation.ts b/workspaces/js/src/core/validation.ts index ea42f31..a2142c1 100644 --- a/workspaces/js/src/core/validation.ts +++ b/workspaces/js/src/core/validation.ts @@ -108,6 +108,8 @@ const TooltipStepStruct: Describe = object({ const ModalStepStruct: Describe = object({ title: string(), body: optional(string()), + hideOverlay: optional(boolean()), + closeOnOverlayClick: optional(boolean()), stepId: optional(string()), hideClose: optional(boolean()), hidePrev: optional(boolean()), diff --git a/workspaces/js/src/types/flow.ts b/workspaces/js/src/types/flow.ts index 3a654a7..56af769 100644 --- a/workspaces/js/src/types/flow.ts +++ b/workspaces/js/src/types/flow.ts @@ -132,6 +132,16 @@ export interface FlowModalStep extends CommonStepProps { * Body of the modal. Supports HTML. */ body?: string; + /** + * Hides modal overlay backdrop and makes rest . + * @defaultValue `false` + */ + hideOverlay?: boolean; + /** + * Cancel the flow when the overlay is clicked. + * @defaultValue `false` + */ + closeOnOverlayClick?: boolean; /** * Hide the close button. Without the close button the user will not be able to close the tooltip. */