aboutsummaryrefslogtreecommitdiff
path: root/examples/docs/src/components/RightSidebar
diff options
context:
space:
mode:
Diffstat (limited to 'examples/docs/src/components/RightSidebar')
-rw-r--r--examples/docs/src/components/RightSidebar/MoreMenu.astro68
-rw-r--r--examples/docs/src/components/RightSidebar/RightSidebar.astro25
-rw-r--r--examples/docs/src/components/RightSidebar/TableOfContents.tsx45
-rw-r--r--examples/docs/src/components/RightSidebar/ThemeToggleButton.css37
-rw-r--r--examples/docs/src/components/RightSidebar/ThemeToggleButton.tsx71
5 files changed, 246 insertions, 0 deletions
diff --git a/examples/docs/src/components/RightSidebar/MoreMenu.astro b/examples/docs/src/components/RightSidebar/MoreMenu.astro
new file mode 100644
index 000000000..6be2d86ee
--- /dev/null
+++ b/examples/docs/src/components/RightSidebar/MoreMenu.astro
@@ -0,0 +1,68 @@
+---
+import ThemeToggleButton from './ThemeToggleButton.jsx';
+const {editHref} = Astro.props;
+---
+<style>
+ .edit-on-github {
+ text-decoration: none;
+ font: inherit;
+ color: inherit;
+ font-size: 1rem;
+ }
+</style>
+<h2 class="heading">More</h2>
+<ul>
+ <li class={`header-link depth-2`}>
+ <a class="edit-on-github" href={editHref} target="_blank">
+ <svg
+ aria-hidden="true"
+ focusable="false"
+ data-prefix="fas"
+ data-icon="pen"
+ class="svg-inline--fa fa-pen fa-w-16"
+ role="img"
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 512 512"
+ height="1em"
+ width="1em"
+ >
+ <path
+ fill="currentColor"
+ 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"
+ ></path>
+ </svg>
+ <span>Edit this page</span>
+ </a>
+ </li>
+ <li class={`header-link depth-2`}>
+ <a href="https://github.com/snowpackjs/astro/blob/main/CONTRIBUTING.md#translations" target="_blank">
+ <svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 88.6 77.3" height="1.24em" width="1.24em" style="margin: -2px;"> <path fill="currentColor" 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" /> <path fill="currentColor" 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" /> </svg>
+ <span>Translate this page</span>
+ </a>
+ </li>
+ <li class={`header-link depth-2`}>
+ <a href="https://astro.build/chat" target="_blank">
+ <svg
+ aria-hidden="true"
+ focusable="false"
+ data-prefix="fas"
+ data-icon="comment-alt"
+ class="svg-inline--fa fa-comment-alt fa-w-16"
+ role="img"
+ xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 512 512"
+ height="1em"
+ width="1em"
+ >
+ <path
+ fill="currentColor"
+ 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"
+ ></path>
+ </svg>
+ <span>Join our community</span>
+ </a>
+ </li>
+</ul>
+<div style="margin: 2rem 0; text-align: center;">
+ <ThemeToggleButton client:visible />
+</div>
diff --git a/examples/docs/src/components/RightSidebar/RightSidebar.astro b/examples/docs/src/components/RightSidebar/RightSidebar.astro
new file mode 100644
index 000000000..ed1dd37cc
--- /dev/null
+++ b/examples/docs/src/components/RightSidebar/RightSidebar.astro
@@ -0,0 +1,25 @@
+---
+import TableOfContents from './TableOfContents.jsx';
+import MoreMenu from './MoreMenu.astro';
+const {content, githubEditUrl} = Astro.props;
+const headers = content.astro.headers;
+---
+<style>
+ .sidebar-nav {
+ width: 100%;
+ position: sticky;
+ top: 0;
+ }
+ .sidebar-nav-inner {
+ height: 100%;
+ padding: 0;
+ padding-top: var(--doc-padding);
+ overflow: auto;
+ }
+</style>
+<nav class="sidebar-nav" aria-labelledby="grid-right">
+ <div class="sidebar-nav-inner">
+ <TableOfContents client:media="(min-width: 50em)" headers={headers} />
+ <MoreMenu editHref={githubEditUrl} />
+ </div>
+</nav> \ No newline at end of file
diff --git a/examples/docs/src/components/RightSidebar/TableOfContents.tsx b/examples/docs/src/components/RightSidebar/TableOfContents.tsx
new file mode 100644
index 000000000..d8ea998d4
--- /dev/null
+++ b/examples/docs/src/components/RightSidebar/TableOfContents.tsx
@@ -0,0 +1,45 @@
+import type { FunctionalComponent } from 'preact';
+import { h, Fragment } from 'preact';
+import { useState, useEffect, useRef } from 'preact/hooks';
+
+const TableOfContents: FunctionalComponent<{ headers: any[] }> = ({ headers = [] }) => {
+ const itemOffsets = useRef([]);
+ const [activeId, setActiveId] = useState<string>(undefined);
+
+ useEffect(() => {
+ const getItemOffsets = () => {
+ const titles = document.querySelectorAll('article :is(h1, h2, h3, h4)');
+ itemOffsets.current = Array.from(titles).map((title) => ({
+ id: title.id,
+ topOffset: title.getBoundingClientRect().top + window.scrollY,
+ }));
+ };
+
+ getItemOffsets();
+ window.addEventListener('resize', getItemOffsets);
+
+ return () => {
+ window.removeEventListener('resize', getItemOffsets);
+ };
+ }, []);
+
+ return (
+ <>
+ <h2 class="heading">On this page</h2>
+ <ul>
+ <li class={`header-link depth-2 ${activeId === 'overview' ? 'active' : ''}`.trim()}>
+ <a href="#overview">Overview</a>
+ </li>
+ {headers
+ .filter(({ depth }) => depth > 1 && depth < 4)
+ .map((header) => (
+ <li class={`header-link depth-${header.depth} ${activeId === header.slug ? 'active' : ''}`.trim()}>
+ <a href={`#${header.slug}`}>{header.text}</a>
+ </li>
+ ))}
+ </ul>
+ </>
+ );
+};
+
+export default TableOfContents;
diff --git a/examples/docs/src/components/RightSidebar/ThemeToggleButton.css b/examples/docs/src/components/RightSidebar/ThemeToggleButton.css
new file mode 100644
index 000000000..7de231d1b
--- /dev/null
+++ b/examples/docs/src/components/RightSidebar/ThemeToggleButton.css
@@ -0,0 +1,37 @@
+.theme-toggle {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.25em;
+ padding: 0.33em 0.67em;
+ border-radius: 99em;
+ background-color: var(--theme-code-inline-bg);
+}
+
+.theme-toggle > label:focus-within {
+ outline: 2px solid transparent;
+ box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
+}
+
+.theme-toggle > label {
+ color: var(--theme-code-inline-text);
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ opacity: 0.5;
+}
+
+.theme-toggle .checked {
+ color: var(--theme-accent);
+ opacity: 1;
+}
+
+input[name='theme-toggle'] {
+ position: absolute;
+ opacity: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: -1;
+}
diff --git a/examples/docs/src/components/RightSidebar/ThemeToggleButton.tsx b/examples/docs/src/components/RightSidebar/ThemeToggleButton.tsx
new file mode 100644
index 000000000..75ea775f4
--- /dev/null
+++ b/examples/docs/src/components/RightSidebar/ThemeToggleButton.tsx
@@ -0,0 +1,71 @@
+import type { FunctionalComponent } from 'preact';
+import { h, Fragment } from 'preact';
+import { useState, useEffect } from 'preact/hooks';
+import './ThemeToggleButton.css';
+
+const themes = ['light', 'dark'];
+
+const icons = [
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
+ <path
+ fillRule="evenodd"
+ d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
+ clipRule="evenodd"
+ />
+ </svg>,
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor">
+ <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
+ </svg>,
+];
+
+const ThemeToggle: FunctionalComponent = () => {
+ const [theme, setTheme] = useState(() => {
+ if (import.meta.env.SSR) {
+ return undefined;
+ }
+ if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
+ return localStorage.getItem('theme');
+ }
+ if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
+ return 'dark';
+ }
+ return 'light';
+ });
+
+ useEffect(() => {
+ const root = document.documentElement;
+ if (theme === 'light') {
+ root.classList.remove('theme-dark');
+ } else {
+ root.classList.add('theme-dark');
+ }
+ }, [theme]);
+
+ return (
+ <div class="theme-toggle">
+ {themes.map((t, i) => {
+ const icon = icons[i];
+ const checked = t === theme;
+ return (
+ <label className={checked ? ' checked' : ''}>
+ {icon}
+ <input
+ type="radio"
+ name="theme-toggle"
+ checked={checked}
+ value={t}
+ title={`Use ${t} theme`}
+ aria-label={`Use ${t} theme`}
+ onChange={() => {
+ localStorage.setItem('theme', t);
+ setTheme(t);
+ }}
+ />
+ </label>
+ );
+ })}
+ </div>
+ );
+};
+
+export default ThemeToggle;