feat: conditional display of scroll to top btn

This commit is contained in:
dragonwocky 2024-01-30 17:57:03 +11:00
parent 42b2fedacf
commit d420b2de4e
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
2 changed files with 85 additions and 37 deletions

View File

@ -0,0 +1,56 @@
/**
* notion-enhancer
* (c) 2024 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
* (https://notion-enhancer.github.io/) under the MIT license
*/
"use strict";
let __$wrapper;
const setupWrapper = () => {
const notionHelp = ".notion-help-button",
{ html, addMutationListener } = globalThis.__enhancerApi,
{ removeMutationListener } = globalThis.__enhancerApi;
return (__$wrapper ??= new Promise((res, rej) => {
const addToDom = () => {
const $help = document.querySelector(notionHelp);
if (!$help) return;
const $wrapper = html`<div
class="notion-enhancer--floating-buttons z-50
absolute right-0 bottom-[calc(26px+env(safe-area-inset-bottom))]
flex gap-[12px] !(&>.notion-help-button:static)"
></div>`;
removeMutationListener(addToDom);
$help.replaceWith($wrapper);
$wrapper.append($help);
res($wrapper);
};
addMutationListener(notionHelp, addToDom);
addToDom();
}));
},
addFloatingButton = async ($btn) => {
if (document.contains($btn)) return;
(await setupWrapper()).prepend($btn);
},
removeFloatingButton = ($btn) => $btn.remove();
function FloatingButton({ icon, ...props }, ...children) {
const { html, extendProps } = globalThis.__enhancerApi;
extendProps(props, {
tabindex: 0,
class: `notion-enhancer--floating-button
size-[36px] flex items-center justify-center rounded-full
text-([20px] [color:var(--theme--fg-primary)]) select-none cursor-pointer
bg-[color:var(--theme--bg-secondary)] hover:bg-[color:var(--theme--bg-hover)]
shadow-[rgba(15,15,15,0.2)_0px_0px_0px_1px,rgba(15,15,15,0.2)_0px_2px_4px]`,
});
return html`<button ...${props}>${children}</button>`;
}
Object.assign((globalThis.__enhancerApi ??= {}), {
addFloatingButton,
removeFloatingButton,
});
export { addFloatingButton, FloatingButton };

View File

@ -7,45 +7,37 @@
"use strict";
import { FloatingButton } from "../../core/islands/FloatingButton.mjs";
export default async (api, db) => {
const { html } = api,
const { html, addFloatingButton, removeFloatingButton } = api,
{ addMutationListener, removeMutationListener } = api,
distanceUntilShown = await db.get("distanceScrolledUntilShown"),
scrollUnits = await db.get("scrollDistanceUnits"),
behavior = (await db.get("smoothScrolling")) ? "smooth" : "auto",
scroller = ".notion-frame > .notion-scroller";
const $btn = html`<button
aria-label="Scroll to top"
class="z-50 flex items-center justify-center absolute rounded-full
text-([20px] [color:var(--theme--fg-primary)]) select-none cursor-pointer
bg-[color:var(--theme--bg-secondary)] hover:bg-[color:var(--theme--bg-hover)]
bottom-[calc(26px+env(safe-area-inset-bottom))] right-[74px] w-[36px] h-[36px]"
style="box-shadow: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 2px 4px;"
onclick=${() => {
const $scroller = document.querySelector(scroller);
$scroller.scroll({ top: 0, left: 0, behavior });
}}
>
<i class="i-chevrons-up" />
</button>`;
document.body.append($btn);
// const topDistancePx = +(await db.get(["top_distance_px"])),
// topDistancePercent = 0.01 * (await db.get(["top_distance_percent"])),
// adjustButtonVisibility = async () => {
// if (!$scroller) return;
// $scrollButton.classList.add("hidden");
// const scrolledDistance =
// $scroller.scrollTop >= topDistancePx ||
// $scroller.scrollTop >=
// ($scroller.scrollHeight - $scroller.clientHeight) *
// topDistancePercent;
// if (scrolledDistance) $scrollButton.classList.remove("hidden");
// };
// web.addDocumentObserver(() => {
// $scroller = document.querySelector(".notion-frame > .notion-scroller");
// $scroller.removeEventListener("scroll", adjustButtonVisibility);
// $scroller.addEventListener("scroll", adjustButtonVisibility);
// }, [".notion-frame > .notion-scroller"]);
// adjustButtonVisibility();
// if (topDistancePx && topDistancePercent)
// $scrollButton.classList.add("hidden");
let $scroller;
const $btn = html`<${FloatingButton}
onclick=${() => $scroller?.scroll({ top: 0, left: 0, behavior })}
aria-label="Scroll to top"
><i class="i-chevrons-up" />
<//>`,
onScroll = () => {
if (!$scroller) return;
const { scrollTop, scrollHeight, clientHeight } = $scroller,
scrollPercent = (scrollTop / (scrollHeight - clientHeight)) * 100,
scrollDist = scrollUnits === "Percent" ? scrollPercent : scrollTop;
if (distanceUntilShown <= scrollDist) addFloatingButton($btn);
else removeFloatingButton($btn);
},
setup = () => {
if (document.contains($scroller)) return;
$scroller = document.querySelector(scroller);
$scroller?.removeEventListener("scroll", onScroll);
$scroller?.addEventListener("scroll", onScroll);
onScroll();
};
addMutationListener(scroller, setup, true);
setup();
};