refactor: improve toc popup module
This commit is contained in:
parent
03e302cbf6
commit
6f461132c0
4 changed files with 49 additions and 34 deletions
|
@ -5,7 +5,10 @@ const desktopMode = matchMedia('(min-width: 1200px)');
|
||||||
|
|
||||||
function refresh(e) {
|
function refresh(e) {
|
||||||
if (e.matches) {
|
if (e.matches) {
|
||||||
|
if (mobile.popupOpened) {
|
||||||
mobile.hidePopup();
|
mobile.hidePopup();
|
||||||
|
}
|
||||||
|
|
||||||
desktop.refresh();
|
desktop.refresh();
|
||||||
} else {
|
} else {
|
||||||
mobile.refresh();
|
mobile.refresh();
|
||||||
|
|
|
@ -12,8 +12,8 @@ const SCROLL_LOCK = 'overflow-hidden';
|
||||||
const CLOSING = 'closing';
|
const CLOSING = 'closing';
|
||||||
|
|
||||||
export class TocMobile {
|
export class TocMobile {
|
||||||
static invisible = true;
|
static #invisible = true;
|
||||||
static barHeight = 16 * 3; // 3rem
|
static #barHeight = 16 * 3; // 3rem
|
||||||
|
|
||||||
static options = {
|
static options = {
|
||||||
tocSelector: '#toc-popup-content',
|
tocSelector: '#toc-popup-content',
|
||||||
|
@ -23,7 +23,7 @@ export class TocMobile {
|
||||||
orderedList: false,
|
orderedList: false,
|
||||||
scrollSmooth: false,
|
scrollSmooth: false,
|
||||||
collapseDepth: 4,
|
collapseDepth: 4,
|
||||||
headingsOffset: this.barHeight
|
headingsOffset: this.#barHeight
|
||||||
};
|
};
|
||||||
|
|
||||||
static initBar() {
|
static initBar() {
|
||||||
|
@ -33,44 +33,40 @@ export class TocMobile {
|
||||||
$tocBar.classList.toggle('invisible', entry.isIntersecting);
|
$tocBar.classList.toggle('invisible', entry.isIntersecting);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ rootMargin: `-${this.barHeight}px 0px 0px 0px` }
|
{ rootMargin: `-${this.#barHeight}px 0px 0px 0px` }
|
||||||
);
|
);
|
||||||
|
|
||||||
observer.observe($soloTrigger);
|
observer.observe($soloTrigger);
|
||||||
this.invisible = false;
|
this.#invisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static listenAnchors() {
|
static listenAnchors() {
|
||||||
const $anchors = document.getElementsByClassName('toc-link');
|
const $anchors = document.getElementsByClassName('toc-link');
|
||||||
[...$anchors].forEach((anchor) => {
|
[...$anchors].forEach((anchor) => {
|
||||||
anchor.onclick = this.hidePopup;
|
anchor.onclick = () => this.hidePopup();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static refresh() {
|
static refresh() {
|
||||||
if (this.invisible) {
|
if (this.#invisible) {
|
||||||
this.initComponents();
|
this.initComponents();
|
||||||
}
|
}
|
||||||
tocbot.refresh(this.options);
|
tocbot.refresh(this.options);
|
||||||
this.listenAnchors();
|
this.listenAnchors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static get popupOpened() {
|
||||||
|
return $popup.open;
|
||||||
|
}
|
||||||
|
|
||||||
static showPopup() {
|
static showPopup() {
|
||||||
TocMobile.lockScroll(true);
|
this.lockScroll(true);
|
||||||
$popup.showModal();
|
$popup.showModal();
|
||||||
const activeItem = $popup.querySelector('li.is-active-li');
|
const activeItem = $popup.querySelector('li.is-active-li');
|
||||||
activeItem.scrollIntoView({ block: 'center' });
|
activeItem.scrollIntoView({ block: 'center' });
|
||||||
}
|
}
|
||||||
|
|
||||||
static hidePopup(event) {
|
static hidePopup() {
|
||||||
if (event?.type === 'cancel') {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$popup.open) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$popup.toggleAttribute(CLOSING);
|
$popup.toggleAttribute(CLOSING);
|
||||||
|
|
||||||
$popup.addEventListener(
|
$popup.addEventListener(
|
||||||
|
@ -82,7 +78,7 @@ export class TocMobile {
|
||||||
{ once: true }
|
{ once: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
TocMobile.lockScroll(false);
|
this.lockScroll(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static lockScroll(enable) {
|
static lockScroll(enable) {
|
||||||
|
@ -91,6 +87,10 @@ export class TocMobile {
|
||||||
}
|
}
|
||||||
|
|
||||||
static clickBackdrop(event) {
|
static clickBackdrop(event) {
|
||||||
|
if ($popup.hasAttribute(CLOSING)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const rect = event.target.getBoundingClientRect();
|
const rect = event.target.getBoundingClientRect();
|
||||||
if (
|
if (
|
||||||
event.clientX < rect.left ||
|
event.clientX < rect.left ||
|
||||||
|
@ -98,7 +98,7 @@ export class TocMobile {
|
||||||
event.clientY < rect.top ||
|
event.clientY < rect.top ||
|
||||||
event.clientY > rect.bottom
|
event.clientY > rect.bottom
|
||||||
) {
|
) {
|
||||||
TocMobile.hidePopup();
|
this.hidePopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,11 +106,15 @@ export class TocMobile {
|
||||||
this.initBar();
|
this.initBar();
|
||||||
|
|
||||||
[...$triggers].forEach((trigger) => {
|
[...$triggers].forEach((trigger) => {
|
||||||
trigger.onclick = this.showPopup;
|
trigger.onclick = () => this.showPopup();
|
||||||
});
|
});
|
||||||
|
|
||||||
$popup.onclick = this.clickBackdrop;
|
$popup.onclick = (e) => this.clickBackdrop(e);
|
||||||
$btnClose.onclick = $popup.oncancel = this.hidePopup;
|
$btnClose.onclick = () => this.hidePopup();
|
||||||
|
$popup.oncancel = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.hidePopup();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
|
|
|
@ -100,7 +100,7 @@ tail_includes:
|
||||||
{% if enable_toc %}
|
{% if enable_toc %}
|
||||||
<div id="toc-bar" class="d-flex align-items-center justify-content-between invisible">
|
<div id="toc-bar" class="d-flex align-items-center justify-content-between invisible">
|
||||||
<span class="label text-truncate">{{ page.title }}</span>
|
<span class="label text-truncate">{{ page.title }}</span>
|
||||||
<button type="button" class="toc-trigger btn btn-link me-1">
|
<button type="button" class="toc-trigger btn me-1">
|
||||||
<i class="fa-solid fa-list-ul fa-fw"></i>
|
<i class="fa-solid fa-list-ul fa-fw"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -113,8 +113,8 @@ tail_includes:
|
||||||
<dialog id="toc-popup" class="p-0">
|
<dialog id="toc-popup" class="p-0">
|
||||||
<div class="header d-flex flex-row align-items-center justify-content-between">
|
<div class="header d-flex flex-row align-items-center justify-content-between">
|
||||||
<div class="label text-truncate py-2 ms-4">{{- page.title -}}</div>
|
<div class="label text-truncate py-2 ms-4">{{- page.title -}}</div>
|
||||||
<button id="toc-popup-close" type="button" class="btn btn-link">
|
<button id="toc-popup-close" type="button" class="btn mx-1 my-1 opacity-75">
|
||||||
<i class="fas fa-close fa-fw"></i>
|
<i class="fas fa-close"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="toc-popup-content" class="px-4 py-3 pb-4"></div>
|
<div id="toc-popup-content" class="px-4 py-3 pb-4"></div>
|
||||||
|
|
|
@ -380,12 +380,13 @@ header {
|
||||||
$slide-in: slide-in 0.3s ease-out;
|
$slide-in: slide-in 0.3s ease-out;
|
||||||
$slide-out: slide-out 0.3s ease-out;
|
$slide-out: slide-out 0.3s ease-out;
|
||||||
$curtain-height: 2rem;
|
$curtain-height: 2rem;
|
||||||
|
$backdrop: blur(5px);
|
||||||
|
|
||||||
border-color: var(--toc-popup-border-color);
|
border-color: var(--toc-popup-border-color);
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-radius: $radius-lg;
|
border-radius: $radius-lg;
|
||||||
color: var(--text-color);
|
color: var(--text-color);
|
||||||
background: var(--main-bg);
|
background: var(--card-bg);
|
||||||
margin-top: $topbar-height;
|
margin-top: $topbar-height;
|
||||||
min-width: 20rem;
|
min-width: 20rem;
|
||||||
font-size: 1.05rem;
|
font-size: 1.05rem;
|
||||||
|
@ -422,9 +423,16 @@ header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button:focus-visible {
|
button {
|
||||||
|
> i {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
@ -461,20 +469,20 @@ header {
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-backdrop {
|
&::-webkit-backdrop {
|
||||||
-webkit-backdrop-filter: blur(5px);
|
-webkit-backdrop-filter: $backdrop;
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: $backdrop;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::backdrop {
|
&::backdrop {
|
||||||
-webkit-backdrop-filter: blur(5px);
|
-webkit-backdrop-filter: $backdrop;
|
||||||
backdrop-filter: blur(5px);
|
backdrop-filter: $backdrop;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
display: flex;
|
display: flex;
|
||||||
content: '';
|
content: '';
|
||||||
position: relative;
|
position: relative;
|
||||||
background: linear-gradient(transparent, var(--main-bg) 70%);
|
background: linear-gradient(transparent, var(--card-bg) 70%);
|
||||||
height: $curtain-height;
|
height: $curtain-height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue