Add bring-in-view functionality

This commit is contained in:
Kamran Ahmed
2023-05-11 04:44:29 +01:00
parent e3d3debcb5
commit 84809869f8
5 changed files with 171 additions and 12 deletions
+122 -8
View File
@@ -19,18 +19,34 @@
-moz-osx-font-smoothing: grayscale;
}
p {
line-height: 1.5;
margin-bottom: 15px;
}
.page-header {
text-align: center;
margin-bottom: 10px;
}
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
max-width: 1200px;
max-width: 500px;
margin: 0 auto;
text-align: left;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 30px 0 10px;
}
h1 {
margin: 40px 0 10px;
font-size: 48px;
font-weight: 600;
text-align: center;
@@ -69,12 +85,23 @@
display: block;
cursor: pointer;
}
pre {
margin-bottom: 20px;
border: 1px solid #ccc;
background: whitesmoke;
border-radius: 5px;
padding: 10px;
line-height: 1.75;
}
</style>
</head>
<body>
<div class="container">
<h1>driver.js <sup>next</sup></h1>
<p>Rewritten and enhanced version of driver.js</p>
<div class="page-header">
<h1>driver.js <sup>next</sup></h1>
<p>Rewritten and enhanced version of driver.js</p>
</div>
<div class="buttons">
<button id="highlight-btn">Animated Highlight</button>
@@ -93,6 +120,91 @@
<li>No dependencies</li>
<li>MIT Licensed</li>
</ul>
<h2>Yet another Tour Library?</h2>
<p>
No, it is not. Tours are just one of the many use-cases. Driver.js can
be used wherever you need some sort of overlay for the page; some common
usecases could be: e.g. dimming the background when user is interacting
with some component, using it as a focus shifter to bring user's
attention to some component on page, or using it to simulate those "Turn
off the Lights" widgets that you might have seen on video players
online, etc.
</p>
<p>
Driver.js is written in Vanilla JS, has zero dependencies and is highly
customizable. It has several options allowing you to manipulate how it
behaves and also provides you the hooks to manipulate the elements as
they are highlighted, about to be highlighted, or deselected.
</p>
<h2>Installation</h2>
<p>You can install it using yarn or npm, whatever you prefer.</p>
<pre>
yarn add driver.js
npm install driver.js</pre
>
<p>
Or include it using CDN — put the version as driver.js@0.5 in the name
</p>
<pre>https://unpkg.com/driver.js/dist/driver.min.js</pre>
<h2>Usage and Demo</h2>
<p id="large-paragraph-text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates! Lorem ipsum dolor sit amet, consectetur
adipisicing elit. Animi blanditiis consectetur ea eligendi id in
inventore ipsa iure laudantium libero, minus molestias necessitatibus
nesciunt non omnis, quasi recusandae tempore voluptates!
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates!
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates!
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates!
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates!
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates!
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates!
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi
blanditiis consectetur ea eligendi id in inventore ipsa iure laudantium
libero, minus molestias necessitatibus nesciunt non omnis, quasi
recusandae tempore voluptates!
</p>
</div>
<script type="module">
import { driver } from "./src/driver.ts";
@@ -104,7 +216,9 @@
document
.getElementById("simple-highlight-btn")
.addEventListener("click", () => {
driver({ animate: false }).highlight({ element: "ul" });
driver({ animate: false }).highlight({
element: "#large-paragraph-text",
});
});
document
+3 -1
View File
@@ -1,13 +1,15 @@
import { Popover } from "./popover";
import { destroyStage } from "./stage";
import { destroyEvents, initEvents } from "./events";
import { Config, configure, getConfig } from "./config";
import { destroyHighlight, highlight } from "./highlight";
import { destroyHooks, register } from "./hooks";
import "./style.css";
import { destroyHooks, register } from "./hooks";
export type DriveStep = {
element?: string | Element;
popover?: Popover;
};
let isInitialized = false;
+5 -3
View File
@@ -2,7 +2,7 @@ import { refreshActiveHighlight } from "./highlight";
let resizeTimeout: number;
function onResize() {
function requireRefresh() {
if (resizeTimeout) {
window.cancelAnimationFrame(resizeTimeout);
}
@@ -64,9 +64,11 @@ export function onDriverClick(
}
export function initEvents() {
window.addEventListener("resize", onResize);
window.addEventListener("resize", requireRefresh);
window.addEventListener("scroll", requireRefresh);
}
export function destroyEvents() {
window.removeEventListener("resize", onResize);
window.removeEventListener("resize", requireRefresh);
window.removeEventListener("scroll", requireRefresh);
}
+29
View File
@@ -1,6 +1,7 @@
import { DriveStep } from "./driver";
import { refreshStage, trackActiveElement, transitionStage } from "./stage";
import { getConfig } from "./config";
import { refreshPopover, renderPopover } from "./popover";
let previousHighlight: Element | undefined;
let activeHighlight: Element | undefined;
@@ -47,11 +48,15 @@ function transferHighlight(from: Element, to: Element) {
if (getConfig("animate") && elapsed < duration) {
transitionStage(elapsed, duration, from, to);
} else {
bringInView(to);
trackActiveElement(to);
renderPopover(to);
currentTransitionCallback = undefined;
}
refreshStage();
refreshPopover();
window.requestAnimationFrame(animate);
};
@@ -62,6 +67,30 @@ function transferHighlight(from: Element, to: Element) {
to.classList.add("driver-active-element");
}
function bringInView(element: Element) {
if (!element || isElementInView(element)) {
return;
}
element.scrollIntoView({
behavior: "smooth",
inline: "center",
block: "center",
});
}
function isElementInView(element: Element) {
const rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <=
(window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
export function destroyHighlight() {
activeHighlight = undefined;
currentTransitionCallback = undefined;
+12
View File
@@ -0,0 +1,12 @@
export type Popover = {
title?: string;
description: string;
preferredPosition?: "top" | "right" | "bottom" | "left";
align?: "start" | "center" | "end";
};
export function renderPopover(element: Element) {
console.log("rendering", element);
}
export function refreshPopover() {}