From 04bbfaa33d3f1579e8dbf9db6f8ec2ecee3d130a Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Sun, 2 Feb 2025 04:23:58 +0000 Subject: [PATCH] Add patch for positioning --- index.html | 13 +++++++++++++ src/popover.ts | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 4f5f1cc..0a1a6eb 100644 --- a/index.html +++ b/index.html @@ -166,6 +166,7 @@

given below are the examples of simple `highlight`

+ @@ -910,6 +911,18 @@ npm install driver.js { + driver().highlight({ + element: ".page-header h1 sup", + popover: { + title: "Buggy Highlight", + description: "Unlike the older version, new version doesn't work with z-indexes so no more positional issues.", + side: "bottom", + align: "start", + }, + }); + }); + document.getElementById("highlight-btn").addEventListener("click", () => { driver({ animate: true, diff --git a/src/popover.ts b/src/popover.ts index 042c402..2e04dbb 100644 --- a/src/popover.ts +++ b/src/popover.ts @@ -1,9 +1,9 @@ -import { bringInView, getFocusableElements } from "./utils"; import { Config, DriverHook, getConfig, getCurrentDriver } from "./config"; -import { getState, setState, State } from "./state"; import { Driver, DriveStep } from "./driver"; -import { onDriverClick } from "./events"; import { emit } from "./emitter"; +import { onDriverClick } from "./events"; +import { getState, setState, State } from "./state"; +import { bringInView, getFocusableElements } from "./utils"; export type Side = "top" | "right" | "bottom" | "left" | "over"; export type Alignment = "start" | "center" | "end"; @@ -585,7 +585,6 @@ function renderPopoverArrow(alignment: Alignment, side: Side, element: Element) arrowSide = "right"; arrowAlignment = "end"; } - } else { } if (!arrowSide) { @@ -593,6 +592,34 @@ function renderPopoverArrow(alignment: Alignment, side: Side, element: Element) } else { popoverArrow.classList.add(`driver-popover-arrow-side-${arrowSide}`); popoverArrow.classList.add(`driver-popover-arrow-align-${arrowAlignment}`); + + const elementRect = element.getBoundingClientRect(); + const arrowRect = popoverArrow.getBoundingClientRect(); + const stagePadding = getConfig("stagePadding") || 0; + + const isElementPartiallyInViewPort = + elementRect.left - stagePadding < window.innerWidth && + elementRect.right + stagePadding > 0 && + elementRect.top - stagePadding < window.innerHeight && + elementRect.bottom + stagePadding > 0; + + if (side === "bottom" && isElementPartiallyInViewPort) { + const isArrowWithinElementBounds = + arrowRect.x > elementRect.x && arrowRect.x + arrowRect.width < elementRect.x + elementRect.width; + + if (!isArrowWithinElementBounds) { + popoverArrow.classList.remove(`driver-popover-arrow-align-${arrowAlignment}`); + popoverArrow.classList.add(`driver-popover-arrow-none`); + // reduce the top position by the padding + popover.wrapper.style.transform = `translateY(-${stagePadding / 2}px)`; + } else { + popover.wrapper.style.transform = `translateY(0)`; + } + + // TODO: implement this using either of the following: + // 1 - move the arrow to the center of the element and point it towards the popover. This way, scrolling or resizing the window will move the arrow to the correct position. + // 2 - calculate the center position of the element and point the arrow towards the popover. However, we will have to re-calculate the position of the arrow when the window is resized or scrolled. + } } }