~james/core

core/docs/src/components/Sidebar.astro -rw-r--r-- 2.7 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 15 hours ago
                                                                                
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
---
// the top of the page lives here instead of a top bar: logo,
// then search, then the nav. the nav is starlight's sidebar data rendered flat:
// group headings and links, no collapsing, no indentation (styles in tangled.css)
import type { StarlightRouteData } from "@astrojs/starlight/route-data";
import Search from "./Search.astro";
import SidebarPersister from "@astrojs/starlight/components/SidebarPersister.astro";
import SiteTitle from "./SiteTitle.astro";

type Entry = StarlightRouteData["sidebar"][number];

const { sidebar } = Astro.locals.starlightRoute;
const links = (entries: Entry[]) => entries.filter((e) => e.type === "link");
---

<div class="sidebar-top sl-hidden md:sl-flex">
  <SiteTitle />
</div>
<div class="sidebar-search"><Search /></div>

<SidebarPersister>
  <nav class="docs-nav">
    {
      sidebar.map((entry) =>
        entry.type === "link" ? (
          <ul>
            <li>
              <a href={entry.href} aria-current={entry.isCurrent ? "page" : undefined}>
                {entry.label}
              </a>
            </li>
          </ul>
        ) : (
          <section>
            <h2>{entry.label}</h2>
            <ul>
              {entry.entries.map((child) =>
                child.type === "link" ? (
                  <li>
                    <a href={child.href} aria-current={child.isCurrent ? "page" : undefined}>
                      {child.label}
                    </a>
                  </li>
                ) : (
                  <li class="subgroup">
                    <h3>{child.label}</h3>
                    <ul>
                      {links(child.entries).map((link) => (
                        <li>
                          <a href={link.href} aria-current={link.isCurrent ? "page" : undefined}>
                            {link.label}
                          </a>
                        </li>
                      ))}
                    </ul>
                  </li>
                ),
              )}
            </ul>
          </section>
        ),
      )
    }
  </nav>
</SidebarPersister>

<!-- the persister restores the last page's scroll; when that leaves the current
     link out of view (a jump from search, say), centre it before first paint -->
<script is:inline aria-hidden="true">
  (() => {
    const scroller = document.getElementById("starlight__sidebar");
    const current = scroller?.querySelector('.docs-nav a[aria-current="page"]');
    if (!scroller || !current) return;
    const view = scroller.getBoundingClientRect();
    const link = current.getBoundingClientRect();
    if (link.top >= view.top && link.bottom <= view.bottom) return;
    scroller.scrollTop += link.top - view.top - (view.height - link.height) / 2;
  })();
</script>