From 5247a23cbe534d79cdf4abe4c200a351dddc5dc2 Mon Sep 17 00:00:00 2001
From: Nate Moore <natemoo-re@users.noreply.github.com>
Date: Thu, 27 May 2021 09:16:14 -0500
Subject: Example: Docs template (#226)

* fix: markdown issues

* wip: add docs example

* example: update doc template

* chore: credit Steph for AvatarList

* chore: align footer to bottom viewport

* chore: feeback R1

* fix: font fallback in firefox

* fix merge conflicts

* fix: add default value to headers

* chore: fix doc example
---
 examples/doc/src/components/DocSidebar.tsx | 55 ++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 examples/doc/src/components/DocSidebar.tsx

(limited to 'examples/doc/src/components/DocSidebar.tsx')

diff --git a/examples/doc/src/components/DocSidebar.tsx b/examples/doc/src/components/DocSidebar.tsx
new file mode 100644
index 000000000..e792851bc
--- /dev/null
+++ b/examples/doc/src/components/DocSidebar.tsx
@@ -0,0 +1,55 @@
+import type { FunctionalComponent } from 'preact';
+import { h } from 'preact';
+import { useState, useEffect, useRef } from 'preact/hooks';
+import EditOnGithub from './EditOnGithub';
+
+const DocSidebar: FunctionalComponent<{ headers: any[]; editHref: string; }> = ({ headers = [], editHref }) => {
+  const itemOffsets = useRef([]);
+  const [activeId, setActiveId] = useState<string>(undefined);
+
+  useEffect(() => {
+    const getItemOffsets = () => {
+      const titles = document.querySelectorAll('article :is(h2, h3, h4)');
+      itemOffsets.current = Array.from(titles).map(title => ({
+        id: title.id,
+        topOffset: title.getBoundingClientRect().top + window.scrollY
+      }));
+    }
+
+    const onScroll = () => {
+      const itemIndex = itemOffsets.current.findIndex(item => item.topOffset > window.scrollY + (window.innerHeight / 3));
+      if (itemIndex === 0) {
+        setActiveId(undefined);
+      } else if (itemIndex === -1) {
+        setActiveId(itemOffsets.current[itemOffsets.current.length - 1].id)
+      } else {
+        setActiveId(itemOffsets.current[itemIndex - 1].id)
+      }
+    }
+
+    getItemOffsets();
+    window.addEventListener('resize', getItemOffsets);
+    window.addEventListener('scroll', onScroll);
+
+    return () => {
+      window.removeEventListener('resize', getItemOffsets);
+      window.removeEventListener('scroll', onScroll);
+    }
+  }, []);
+
+  return (
+    <nav>
+      <div>
+        <h4>Contents</h4>
+        <ul>
+          {headers.filter(({ depth }) => depth > 1 && depth < 5).map(header => <li class={`header-link depth-${header.depth} ${activeId === header.slug ? 'active' : ''}`.trim()}><a href={`#${header.slug}`}>{header.text}</a></li>)}
+        </ul>
+      </div>
+      <div>
+        <EditOnGithub href={editHref} />
+      </div>
+    </nav>    
+  );
+}
+
+export default DocSidebar;
-- 
cgit v1.2.3

