xs-dev 0.14.2 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +4 -0
  2. package/build/commands/include.js +9 -7
  3. package/build/commands/remove.js +5 -5
  4. package/build/commands/scan.js +8 -4
  5. package/build/toolbox/setup/esp32.js +2 -2
  6. package/build/toolbox/setup/fontbm.js +7 -3
  7. package/build/toolbox/update/esp32.js +4 -4
  8. package/docs/astro.config.mjs +13 -0
  9. package/docs/public/favicon.ico +0 -0
  10. package/docs/public/make-scrollable-code-focusable.js +3 -0
  11. package/docs/src/components/Footer/AvatarList.astro +149 -0
  12. package/docs/src/components/Footer/Footer.astro +16 -0
  13. package/docs/src/components/HeadCommon.astro +41 -0
  14. package/docs/src/components/HeadSEO.astro +34 -0
  15. package/docs/src/components/Header/Header.astro +133 -0
  16. package/docs/src/components/Header/LanguageSelect.css +47 -0
  17. package/docs/src/components/Header/LanguageSelect.tsx +49 -0
  18. package/docs/src/components/Header/Search.css +39 -0
  19. package/docs/src/components/Header/Search.tsx +65 -0
  20. package/docs/src/components/Header/SidebarToggle.tsx +44 -0
  21. package/docs/src/components/Header/SkipToContent.astro +22 -0
  22. package/docs/src/components/LeftSidebar/LeftSidebar.astro +118 -0
  23. package/docs/src/components/PageContent/PageContent.astro +41 -0
  24. package/docs/src/components/RightSidebar/MoreMenu.astro +70 -0
  25. package/docs/src/components/RightSidebar/RightSidebar.astro +27 -0
  26. package/docs/src/components/RightSidebar/TableOfContents.tsx +49 -0
  27. package/docs/src/components/RightSidebar/ThemeToggleButton.css +37 -0
  28. package/docs/src/components/RightSidebar/ThemeToggleButton.tsx +83 -0
  29. package/docs/src/config.ts +43 -0
  30. package/docs/src/languages.ts +10 -0
  31. package/docs/src/layouts/MainLayout.astro +122 -0
  32. package/docs/src/pages/en/features/include.md +48 -0
  33. package/docs/src/pages/en/features/init.md +57 -0
  34. package/docs/src/pages/en/features/run.md +63 -0
  35. package/docs/src/pages/en/features/scan.md +28 -0
  36. package/docs/src/pages/en/features/setup.md +55 -0
  37. package/docs/src/pages/en/features/teardown.md +13 -0
  38. package/docs/src/pages/en/features/update.md +21 -0
  39. package/docs/src/pages/en/introduction.md +68 -0
  40. package/docs/src/pages/index.astro +5 -0
  41. package/docs/src/pages/search-index.json.ts +18 -0
  42. package/docs/src/styles/index.css +382 -0
  43. package/docs/src/styles/theme.css +125 -0
  44. package/docs/tailwind.config.cjs +7 -0
  45. package/docs/tsconfig.json +15 -0
  46. package/package.json +24 -6
  47. package/docs/commands.md +0 -3
  48. package/docs/plugins.md +0 -47
@@ -0,0 +1,133 @@
1
+ ---
2
+ import { getLanguageFromURL, KNOWN_LANGUAGE_CODES } from '../../languages.ts';
3
+ import * as CONFIG from '../../config.ts';
4
+ import SkipToContent from './SkipToContent.astro';
5
+ import SidebarToggle from './SidebarToggle.tsx';
6
+ import LanguageSelect from './LanguageSelect.tsx';
7
+ import Search from './Search.tsx';
8
+
9
+ const { currentPage } = Astro.props;
10
+ const lang = currentPage && getLanguageFromURL(currentPage);
11
+ ---
12
+
13
+ <header>
14
+ <SkipToContent />
15
+ <nav class="nav-wrapper" title="Top Navigation">
16
+ <div class="menu-toggle">
17
+ <SidebarToggle client:idle />
18
+ </div>
19
+ <div class="logo flex">
20
+ <a href={Astro.site}>
21
+ <h1>{CONFIG.SITE.title ?? "Documentation"}</h1>
22
+ </a>
23
+ </div>
24
+ <div style="flex-grow: 1;"></div>
25
+ {KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle />}
26
+ </nav>
27
+ <Search client:idle />
28
+ </header>
29
+
30
+ <style>
31
+ header {
32
+ z-index: 11;
33
+ height: var(--theme-navbar-height);
34
+ width: 100%;
35
+ background-color: var(--theme-navbar-bg);
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ position: sticky;
40
+ top: 0;
41
+ }
42
+
43
+ .logo {
44
+ flex: 1;
45
+ display: flex;
46
+ overflow: hidden;
47
+ width: 30px;
48
+ font-size: 2rem;
49
+ flex-shrink: 0;
50
+ font-weight: 600;
51
+ line-height: 1;
52
+ color: hsla(var(--color-base-white), 100%, 1);
53
+ gap: 0.25em;
54
+ z-index: -1;
55
+ }
56
+
57
+ .logo a {
58
+ display: flex;
59
+ padding: 0.5em 0.25em;
60
+ margin: -0.5em -0.25em;
61
+ text-decoration: none;
62
+ font-weight: bold;
63
+ }
64
+
65
+ .logo a {
66
+ transition: color 100ms ease-out;
67
+ color: var(--theme-text);
68
+ }
69
+
70
+ .logo a:hover,
71
+ .logo a:focus {
72
+ color: var(--theme-text-accent);
73
+ }
74
+
75
+ .logo h1 {
76
+ display: none;
77
+ font: inherit;
78
+ color: inherit;
79
+ margin: 0;
80
+ }
81
+
82
+ .nav-wrapper {
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: flex-end;
86
+ gap: 1em;
87
+ width: 100%;
88
+ max-width: 82em;
89
+ padding: 0 1rem;
90
+ }
91
+
92
+ @media (min-width: 50em) {
93
+ header {
94
+ position: static;
95
+ padding: 2rem 0rem;
96
+ }
97
+ .logo {
98
+ width: auto;
99
+ margin: 0;
100
+ z-index: 0;
101
+ }
102
+ .logo h1 {
103
+ display: initial;
104
+ }
105
+ .menu-toggle {
106
+ display: none;
107
+ }
108
+ }
109
+
110
+ /** Style Algolia */
111
+ :root {
112
+ --docsearch-primary-color: var(--theme-accent);
113
+ --docsearch-logo-color: var(--theme-text);
114
+ }
115
+
116
+ .search-item {
117
+ display: none;
118
+ position: relative;
119
+ z-index: 10;
120
+ flex-grow: 1;
121
+ padding-right: 0.7rem;
122
+ display: flex;
123
+ max-width: 200px;
124
+ }
125
+ :global(.search-item > *) {
126
+ flex-grow: 1;
127
+ }
128
+ @media (min-width: 50em) {
129
+ .search-item {
130
+ max-width: 400px;
131
+ }
132
+ }
133
+ </style>
@@ -0,0 +1,47 @@
1
+ .language-select {
2
+ flex-grow: 1;
3
+ width: 48px;
4
+ box-sizing: border-box;
5
+ margin: 0;
6
+ padding: 0.33em 0.5em;
7
+ overflow: visible;
8
+ font-weight: 500;
9
+ font-size: 1rem;
10
+ font-family: inherit;
11
+ line-height: inherit;
12
+ background-color: var(--theme-bg);
13
+ border-color: var(--theme-text-lighter);
14
+ color: var(--theme-text-light);
15
+ border-style: solid;
16
+ border-width: 1px;
17
+ border-radius: 0.25rem;
18
+ outline: 0;
19
+ cursor: pointer;
20
+ transition-timing-function: ease-out;
21
+ transition-duration: 0.2s;
22
+ transition-property: border-color, color;
23
+ -webkit-font-smoothing: antialiased;
24
+ padding-left: 30px;
25
+ padding-right: 1rem;
26
+ }
27
+ .language-select-wrapper .language-select:hover,
28
+ .language-select-wrapper .language-select:focus {
29
+ color: var(--theme-text);
30
+ border-color: var(--theme-text-light);
31
+ }
32
+ .language-select-wrapper {
33
+ color: var(--theme-text-light);
34
+ position: relative;
35
+ }
36
+ .language-select-wrapper > svg {
37
+ position: absolute;
38
+ top: 7px;
39
+ left: 10px;
40
+ pointer-events: none;
41
+ }
42
+
43
+ @media (min-width: 50em) {
44
+ .language-select {
45
+ width: 100%;
46
+ }
47
+ }
@@ -0,0 +1,49 @@
1
+ import type { FunctionalComponent } from 'preact';
2
+ import { h } from 'preact';
3
+ import './LanguageSelect.css';
4
+ import { KNOWN_LANGUAGES, langPathRegex } from '../../languages';
5
+
6
+ const LanguageSelect: FunctionalComponent<{ lang: string }> = ({ lang }) => {
7
+ return (
8
+ <div class="language-select-wrapper">
9
+ <svg
10
+ aria-hidden="true"
11
+ focusable="false"
12
+ role="img"
13
+ xmlns="http://www.w3.org/2000/svg"
14
+ viewBox="0 0 88.6 77.3"
15
+ height="1.2em"
16
+ width="1.2em"
17
+ >
18
+ <path
19
+ fill="currentColor"
20
+ d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z"
21
+ />
22
+ <path
23
+ fill="currentColor"
24
+ d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
25
+ />
26
+ </svg>
27
+ <select
28
+ class="language-select"
29
+ value={lang}
30
+ onChange={(e) => {
31
+ const newLang = e.target.value;
32
+ let actualDest = window.location.pathname.replace(langPathRegex, '/');
33
+ if (actualDest == '/') actualDest = `/introduction`;
34
+ window.location.pathname = '/' + newLang + actualDest;
35
+ }}
36
+ >
37
+ {Object.keys(KNOWN_LANGUAGES).map((key) => {
38
+ return (
39
+ <option value={KNOWN_LANGUAGES[key]}>
40
+ <span>{key}</span>
41
+ </option>
42
+ );
43
+ })}
44
+ </select>
45
+ </div>
46
+ );
47
+ };
48
+
49
+ export default LanguageSelect;
@@ -0,0 +1,39 @@
1
+ .flex-column {
2
+ flex-direction: column;
3
+ }
4
+
5
+ .SearchContainer {
6
+ position: relative;
7
+ }
8
+
9
+ .SearchContainer-input {
10
+ border: 1px solid #333333;
11
+ padding: 0.5rem 1rem;
12
+ }
13
+
14
+ .SearchContainer-button {
15
+ border-radius: 0px;
16
+ padding: 0.5rem;
17
+ }
18
+
19
+ .SearchContainer-list {
20
+ background: white;
21
+ top: 2.6rem;
22
+ display: flex;
23
+ flex-direction: column;
24
+ left: 0;
25
+ position: absolute;
26
+ width: 100%;
27
+ }
28
+
29
+ .SearchContainer-list.has-results {
30
+ border: 1px solid #333333;
31
+ }
32
+
33
+ .SearchContainer-list_item {
34
+ padding: 0.5rem 1rem;
35
+ }
36
+
37
+ .SearchContainer-link {
38
+ color: blue;
39
+ }
@@ -0,0 +1,65 @@
1
+ import type { FunctionalComponent } from 'preact'
2
+ import { h, Fragment } from 'preact'
3
+ import { useEffect, useRef, useState } from 'preact/hooks'
4
+ import Fuse from 'fuse.js'
5
+ import './Search.css'
6
+
7
+ const SearchForm: FunctionalComponent = () => {
8
+ const fuse = useRef(null)
9
+ const [results, setResults] = useState([])
10
+
11
+ const searchContent = (event: SubmitEvent) => {
12
+ event.preventDefault()
13
+ const data = Object.fromEntries(
14
+ new FormData(event.currentTarget as HTMLFormElement)
15
+ )
16
+ const result = fuse.current.search(data.search)
17
+ setResults(result.map(({ item }) => item))
18
+ }
19
+
20
+ useEffect(() => {
21
+ fetch('/xs-dev/search-index.json')
22
+ .then((res) => res.json())
23
+ .then((content) => {
24
+ const options = { keys: ['title', 'description', 'content'] }
25
+ fuse.current = new Fuse(content, options)
26
+ })
27
+ }, [])
28
+
29
+ return (
30
+ <div class="flex flex-column SearchContainer">
31
+ <form method="GET" id="search-form" onSubmit={searchContent}>
32
+ <div role="search" class="flex flex-row">
33
+ <input
34
+ type="search"
35
+ id="search"
36
+ name="search"
37
+ aria-label="search documentation content"
38
+ placeholder="search documentation content"
39
+ class="SearchContainer-input"
40
+ />
41
+ <button type="submit" class="SearchContainer-button">
42
+ Search
43
+ </button>
44
+ </div>
45
+ </form>
46
+ <ul
47
+ class={`SearchContainer-list ${
48
+ results.length > 0 ? 'has-results' : undefined
49
+ }`}
50
+ aria-live="assertive"
51
+ aria-atomic="true"
52
+ >
53
+ {results.map((result) => (
54
+ <li class="SearchContainer-list_item">
55
+ <a href={result.url} class="SearchContainer-link">
56
+ {result.title}
57
+ </a>
58
+ </li>
59
+ ))}
60
+ </ul>
61
+ </div>
62
+ )
63
+ }
64
+
65
+ export default SearchForm
@@ -0,0 +1,44 @@
1
+ import type { FunctionalComponent } from 'preact';
2
+ import { h, Fragment } from 'preact';
3
+ import { useState, useEffect } from 'preact/hooks';
4
+
5
+ const MenuToggle: FunctionalComponent = () => {
6
+ const [sidebarShown, setSidebarShown] = useState(false);
7
+
8
+ useEffect(() => {
9
+ const body = document.getElementsByTagName('body')[0];
10
+ if (sidebarShown) {
11
+ body.classList.add('mobile-sidebar-toggle');
12
+ } else {
13
+ body.classList.remove('mobile-sidebar-toggle');
14
+ }
15
+ }, [sidebarShown]);
16
+
17
+ return (
18
+ <button
19
+ type="button"
20
+ aria-pressed={sidebarShown ? 'true' : 'false'}
21
+ id="menu-toggle"
22
+ onClick={() => setSidebarShown(!sidebarShown)}
23
+ >
24
+ <svg
25
+ xmlns="http://www.w3.org/2000/svg"
26
+ width="1em"
27
+ height="1em"
28
+ fill="none"
29
+ viewBox="0 0 24 24"
30
+ stroke="currentColor"
31
+ >
32
+ <path
33
+ stroke-linecap="round"
34
+ stroke-linejoin="round"
35
+ stroke-width="2"
36
+ d="M4 6h16M4 12h16M4 18h16"
37
+ />
38
+ </svg>
39
+ <span className="sr-only">Toggle sidebar</span>
40
+ </button>
41
+ );
42
+ };
43
+
44
+ export default MenuToggle;
@@ -0,0 +1,22 @@
1
+ <a href="#article" class="sr-only focus:not-sr-only skiplink"><span>Skip to Content</span></a>
2
+
3
+ <style>
4
+ .skiplink,
5
+ .skiplink:focus,
6
+ .skiplink:focus-visible {
7
+ position: absolute;
8
+ padding: 0.25em;
9
+ font-size: larger;
10
+ top: 0;
11
+ left: 0;
12
+ right: 0;
13
+ z-index: 9;
14
+ display: block;
15
+ text-align: center;
16
+ background-color: var(--theme-text-accent);
17
+ color: var(--theme-bg);
18
+ border-radius: 0.25em;
19
+ outline: var(--theme-bg) solid 1px;
20
+ outline-offset: 0;
21
+ }
22
+ </style>
@@ -0,0 +1,118 @@
1
+ ---
2
+ import { getLanguageFromURL } from '../../languages.ts';
3
+ import { SIDEBAR } from '../../config.ts';
4
+ const { currentPage } = Astro.props;
5
+ const currentPageMatch = currentPage.slice(1);
6
+ const langCode = getLanguageFromURL(currentPage);
7
+ // SIDEBAR is a flat array. Group it by sections to properly render.
8
+ const sidebarSections = SIDEBAR[langCode].reduce((col, item, i) => {
9
+ // If the first item is not a section header, create a new container section.
10
+ if (i === 0) {
11
+ if (!item.header) {
12
+ const pesudoSection = { text: "" };
13
+ col.push({ ...pesudoSection, children: [] });
14
+ }
15
+ }
16
+ if (item.header) {
17
+ col.push({ ...item, children: [] });
18
+ } else {
19
+ col[col.length - 1].children.push(item);
20
+ }
21
+ return col;
22
+ }, []);
23
+ ---
24
+
25
+ <nav aria-labelledby="grid-left">
26
+ <ul class="nav-groups">
27
+ {sidebarSections.map((section) => (
28
+ <li>
29
+ <div class="nav-group">
30
+ <h2 class="nav-group-title">{section.text}</h2>
31
+ <ul>
32
+ {section.children.map((child) => (
33
+ <li class="nav-link">
34
+ <a href={`${Astro.site.pathname}${child.link}`} aria-current={`${currentPageMatch === child.link ? 'page' : 'false'}`}>
35
+ {child.text}
36
+ </a>
37
+ </li>
38
+ ))}
39
+ </ul>
40
+ </div>
41
+ </li>
42
+ ))}
43
+ </ul>
44
+ </nav>
45
+
46
+ <script is:inline>
47
+ window.addEventListener('DOMContentLoaded', (event) => {
48
+ var target = document.querySelector('[aria-current="page"]');
49
+ if (target && target.offsetTop > window.innerHeight - 100) {
50
+ document.querySelector('.nav-groups').scrollTop = target.offsetTop;
51
+ }
52
+ });
53
+ </script>
54
+
55
+ <style>
56
+ nav {
57
+ width: 100%;
58
+ margin-right: 1rem;
59
+ }
60
+ .nav-groups {
61
+ height: 100%;
62
+ padding: 2rem 0;
63
+ overflow-x: visible;
64
+ overflow-y: auto;
65
+ max-height: 100vh;
66
+ }
67
+
68
+ .nav-groups > li + li {
69
+ margin-top: 2rem;
70
+ }
71
+
72
+ .nav-groups > :first-child {
73
+ padding-top: var(--doc-padding);
74
+ }
75
+
76
+ .nav-groups > :last-child {
77
+ padding-bottom: 2rem;
78
+ margin-bottom: var(--theme-navbar-height);
79
+ }
80
+
81
+ .nav-group-title {
82
+ font-size: 1rem;
83
+ font-weight: 700;
84
+ padding: 0.1rem 1rem;
85
+ text-transform: uppercase;
86
+ margin-bottom: 0.5rem;
87
+ }
88
+
89
+ .nav-link a {
90
+ font-size: 1rem;
91
+ margin: 1px;
92
+ padding: 0.3rem 1rem;
93
+ font: inherit;
94
+ color: inherit;
95
+ text-decoration: none;
96
+ display: block;
97
+ }
98
+ .nav-link a:hover,
99
+ .nav-link a:focus {
100
+ background-color: var(--theme-bg-hover);
101
+ }
102
+
103
+ .nav-link a[aria-current='page'] {
104
+ color: var(--theme-text-accent);
105
+ background-color: var(--theme-bg-accent);
106
+ font-weight: 600;
107
+ }
108
+
109
+ :global(:root.theme-dark) .nav-link a[aria-current='page'] {
110
+ color: hsla(var(--color-base-white), 100%, 1);
111
+ }
112
+
113
+ @media (min-width: 50em) {
114
+ .nav-groups {
115
+ padding: 0;
116
+ }
117
+ }
118
+ </style>
@@ -0,0 +1,41 @@
1
+ ---
2
+ import MoreMenu from '../RightSidebar/MoreMenu.astro';
3
+ import TableOfContents from '../RightSidebar/TableOfContents.tsx';
4
+
5
+ const { content, githubEditUrl } = Astro.props;
6
+ const title = content.title;
7
+ const headers = content.astro.headers;
8
+ ---
9
+
10
+ <article id="article" class="content">
11
+ <section class="main-section">
12
+ <h1 class="content-title" id="overview">{title}</h1>
13
+ <slot />
14
+ </section>
15
+ <nav class="block sm:hidden">
16
+ <MoreMenu editHref={githubEditUrl} />
17
+ </nav>
18
+ </article>
19
+
20
+ <style>
21
+ .content {
22
+ padding: 0;
23
+ max-width: 75ch;
24
+ width: 100%;
25
+ height: 100%;
26
+ display: flex;
27
+ flex-direction: column;
28
+ }
29
+ .content > section {
30
+ margin-bottom: 4rem;
31
+ }
32
+ .block {
33
+ display: block;
34
+ }
35
+
36
+ @media (min-width: 50em) {
37
+ .sm\:hidden {
38
+ display: none;
39
+ }
40
+ }
41
+ </style>
@@ -0,0 +1,70 @@
1
+ ---
2
+ import ThemeToggleButton from './ThemeToggleButton.tsx';
3
+ import * as CONFIG from '../../config';
4
+ const { editHref } = Astro.props;
5
+ const showMoreSection = CONFIG.COMMUNITY_INVITE_URL || editHref;
6
+ ---
7
+
8
+ {showMoreSection && <h2 class="heading">More</h2>}
9
+ <ul>
10
+ {editHref && (
11
+ <li class={`header-link depth-2`}>
12
+ <a class="edit-on-github" href={editHref} target="_blank">
13
+ <svg
14
+ aria-hidden="true"
15
+ focusable="false"
16
+ data-prefix="fas"
17
+ data-icon="pen"
18
+ class="svg-inline--fa fa-pen fa-w-16"
19
+ role="img"
20
+ xmlns="http://www.w3.org/2000/svg"
21
+ viewBox="0 0 512 512"
22
+ height="1em"
23
+ width="1em"
24
+ >
25
+ <path
26
+ fill="currentColor"
27
+ d="M290.74 93.24l128.02 128.02-277.99 277.99-114.14 12.6C11.35 513.54-1.56 500.62.14 485.34l12.7-114.22 277.9-277.88zm207.2-19.06l-60.11-60.11c-18.75-18.75-49.16-18.75-67.91 0l-56.55 56.55 128.02 128.02 56.55-56.55c18.75-18.76 18.75-49.16 0-67.91z"
28
+ ></path>
29
+ </svg>
30
+ <span>Edit this page</span>
31
+ </a>
32
+ </li>
33
+ )}
34
+ {CONFIG.COMMUNITY_INVITE_URL && (
35
+ <li class={`header-link depth-2`}>
36
+ <a href={CONFIG.COMMUNITY_INVITE_URL} target="_blank">
37
+ <svg
38
+ aria-hidden="true"
39
+ focusable="false"
40
+ data-prefix="fas"
41
+ data-icon="comment-alt"
42
+ class="svg-inline--fa fa-comment-alt fa-w-16"
43
+ role="img"
44
+ xmlns="http://www.w3.org/2000/svg"
45
+ viewBox="0 0 512 512"
46
+ height="1em"
47
+ width="1em"
48
+ >
49
+ <path
50
+ fill="currentColor"
51
+ d="M448 0H64C28.7 0 0 28.7 0 64v288c0 35.3 28.7 64 64 64h96v84c0 9.8 11.2 15.5 19.1 9.7L304 416h144c35.3 0 64-28.7 64-64V64c0-35.3-28.7-64-64-64z"
52
+ ></path>
53
+ </svg>
54
+ <span>Join our community</span>
55
+ </a>
56
+ </li>
57
+ )}
58
+ </ul>
59
+ <div style="margin: 2rem 0; text-align: center;">
60
+ <ThemeToggleButton client:visible />
61
+ </div>
62
+
63
+ <style>
64
+ .edit-on-github {
65
+ text-decoration: none;
66
+ font: inherit;
67
+ color: inherit;
68
+ font-size: 1rem;
69
+ }
70
+ </style>
@@ -0,0 +1,27 @@
1
+ ---
2
+ import TableOfContents from './TableOfContents.tsx';
3
+ import MoreMenu from './MoreMenu.astro';
4
+ const { content, githubEditUrl } = Astro.props;
5
+ const headers = content.astro.headers;
6
+ ---
7
+
8
+ <nav class="sidebar-nav" aria-labelledby="grid-right">
9
+ <div class="sidebar-nav-inner">
10
+ <TableOfContents client:media="(min-width: 50em)" {headers} />
11
+ <MoreMenu editHref={githubEditUrl} />
12
+ </div>
13
+ </nav>
14
+
15
+ <style>
16
+ .sidebar-nav {
17
+ width: 100%;
18
+ position: sticky;
19
+ top: 0;
20
+ }
21
+ .sidebar-nav-inner {
22
+ height: 100%;
23
+ padding: 0;
24
+ padding-top: var(--doc-padding);
25
+ overflow: auto;
26
+ }
27
+ </style>