-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathsidebar-scroll.js
More file actions
79 lines (71 loc) · 2.43 KB
/
Copy pathsidebar-scroll.js
File metadata and controls
79 lines (71 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
(function () {
if (typeof window === "undefined") return;
// Mintlify's DOM is not a stable contract, so selection is defensive:
// pick the first sidebar-ish element that is actually scrollable.
function findSidebar() {
var candidates = document.querySelectorAll(
"aside, nav[aria-label='Sidebar'], aside[aria-label='Sidebar'], #sidebar"
);
for (var i = 0; i < candidates.length; i++) {
var el = candidates[i];
if (el.scrollHeight > el.clientHeight + 1) return el;
}
return null;
}
function findActiveLink(sb) {
return sb.querySelector(
"a[aria-current='page'], a[aria-current='true'], a[data-active='true']"
);
}
// Scroll the sidebar the minimum amount needed to bring the current page's
// link into view. No-op if it's already visible. Anchored to the active
// item (semantic) rather than a remembered pixel offset, so it stays correct
// even when the sidebar's contents differ between pages.
function showActive() {
var sb = findSidebar();
if (!sb) return false;
var link = findActiveLink(sb);
if (!link) return false;
var sbRect = sb.getBoundingClientRect();
var linkRect = link.getBoundingClientRect();
var margin = 24; // breathing room so the item isn't flush against an edge
if (linkRect.top < sbRect.top + margin) {
sb.scrollTop -= sbRect.top + margin - linkRect.top;
} else if (linkRect.bottom > sbRect.bottom - margin) {
sb.scrollTop += linkRect.bottom - (sbRect.bottom - margin);
}
return true;
}
// After a route change the sidebar may not exist yet; poll until it does.
// On success, re-apply once more to survive a late re-render that resets it.
function pollShow() {
var attempts = 0;
var iv = setInterval(function () {
attempts++;
if (showActive()) {
clearInterval(iv);
setTimeout(showActive, 150);
} else if (attempts > 30) {
clearInterval(iv);
}
}, 50);
}
var origPush = history.pushState;
history.pushState = function () {
var r = origPush.apply(this, arguments);
pollShow();
return r;
};
var origReplace = history.replaceState;
history.replaceState = function () {
var r = origReplace.apply(this, arguments);
pollShow();
return r;
};
window.addEventListener("popstate", pollShow);
if (document.readyState === "complete") {
pollShow();
} else {
window.addEventListener("load", pollShow);
}
})();