summaryrefslogtreecommitdiff
path: root/_shared/docs.js
diff options
context:
space:
mode:
authort <t@tjp.lol>2026-06-16 19:28:54 -0600
committert <t@tjp.lol>2026-06-16 20:21:55 -0600
commitc21a4ebd001ca305d862b5390f090f2ef14163cf (patch)
tree6910b11139c6b01c78a64c18b206d89619bebbf1 /_shared/docs.js
base site: claude design plus some tweaks
Diffstat (limited to '_shared/docs.js')
-rw-r--r--_shared/docs.js85
1 files changed, 85 insertions, 0 deletions
diff --git a/_shared/docs.js b/_shared/docs.js
new file mode 100644
index 0000000..7e07310
--- /dev/null
+++ b/_shared/docs.js
@@ -0,0 +1,85 @@
+/* panto docs — progressive enhancement only.
+ The site is fully functional with this file absent or JS disabled:
+ every nav item is a real link, all content is in the HTML. This adds
+ the mobile sidebar toggle, code copy buttons, and TOC scroll-spy. */
+(function () {
+ 'use strict';
+
+ /* ---- Mobile sidebar toggle ---------------------------------------- */
+ var menuBtn = document.querySelector('[data-menu-toggle]');
+ var sidebar = document.querySelector('.pd-sidebar');
+ var scrim = document.querySelector('.pd-scrim');
+ function closeMenu() {
+ if (sidebar) sidebar.classList.remove('pd-sidebar--open');
+ }
+ if (menuBtn && sidebar) {
+ menuBtn.addEventListener('click', function () {
+ sidebar.classList.toggle('pd-sidebar--open');
+ });
+ }
+ if (scrim) scrim.addEventListener('click', closeMenu);
+ if (sidebar) {
+ sidebar.addEventListener('click', function (e) {
+ if (e.target.closest('a')) closeMenu();
+ });
+ }
+
+ /* ---- Code copy buttons -------------------------------------------- */
+ document.querySelectorAll('.pg-code__copy').forEach(function (btn) {
+ btn.addEventListener('click', function () {
+ var block = btn.closest('.pg-code');
+ var pre = block && block.querySelector('pre');
+ if (!pre) return;
+ var text = pre.innerText;
+ var done = function () {
+ btn.classList.add('pg-code__copy--done');
+ var label = btn.querySelector('.pg-code__label');
+ if (label) label.textContent = 'Copied';
+ setTimeout(function () {
+ btn.classList.remove('pg-code__copy--done');
+ if (label) label.textContent = 'Copy';
+ }, 1400);
+ };
+ if (navigator.clipboard) navigator.clipboard.writeText(text).then(done, done);
+ else done();
+ });
+ });
+
+ /* ---- Scroll-spy: highlight the active section in TOC + sidebar ---- */
+ var tocLinks = Array.prototype.slice.call(document.querySelectorAll('.pd-toc__link'));
+ var sideLinks = Array.prototype.slice.call(
+ document.querySelectorAll('.pd-navsec--current .pd-navsec__link')
+ );
+ if (!tocLinks.length || !('IntersectionObserver' in window)) return;
+
+ var ids = tocLinks.map(function (a) {
+ var href = a.getAttribute('href') || '';
+ return href.charAt(0) === '#' ? href.slice(1) : href.split('#')[1];
+ }).filter(Boolean);
+
+ function setActive(id) {
+ tocLinks.forEach(function (a) {
+ var h = a.getAttribute('href') || '';
+ a.classList.toggle('pd-toc__link--active', h === '#' + id);
+ });
+ sideLinks.forEach(function (a) {
+ var h = a.getAttribute('href') || '';
+ a.classList.toggle('pd-navsec__link--active', h.split('#')[1] === id);
+ });
+ }
+
+ var visible = new Set();
+ var obs = new IntersectionObserver(function (entries) {
+ entries.forEach(function (e) {
+ if (e.isIntersecting) visible.add(e.target.id);
+ else visible.delete(e.target.id);
+ });
+ var first = ids.find(function (id) { return visible.has(id); });
+ if (first) setActive(first);
+ }, { rootMargin: '-72px 0px -68% 0px', threshold: 0 });
+
+ ids.forEach(function (id) {
+ var el = document.getElementById(id);
+ if (el) obs.observe(el);
+ });
+})();