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..83a2129 --- /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. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit.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..6948fe3 100644 --- a/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.html +++ b/workspaces/e2e/tests/tooltip-overlay/tooltip-overlay.html @@ -11,7 +11,7 @@

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/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. */