diff options
| author | Leitwolf | 2026-10-18 09:57:50 +0300 |
|---|---|---|
| committer | GitHub | 2026-10-18 09:57:50 +0300 |
| commit | 5877c2ec7f0f58eb4128c83e20d93fd74c90a47d (patch) | |
| tree | 4760813c7550a29ee25160f70cf91b2f5bd552cd | |
| parent | c2eb3d208b37826167496cfdf657ffca33fef703 (diff) | |
| parent | 47ffd40c8b61aa9dd131e567bfb2ce78ec7f354c (diff) | |
| download | website-5877c2ec7f0f58eb4128c83e20d93fd74c90a47d.tar.gz | |
Merge pull request #41 from Progmasoft/design/docs-layout
Lay out the documentation like kotlinlang.org/docs
| -rw-r--r-- | frontend/src/components/DocShell.vue | 161 | ||||
| -rw-r--r-- | frontend/src/pages/DocPage.vue | 76 | ||||
| -rw-r--r-- | frontend/src/pages/GettingStartedPage.vue | 116 | ||||
| -rw-r--r-- | frontend/src/pages/OverviewPage.vue | 114 | ||||
| -rw-r--r-- | frontend/src/styles/site.css | 203 |
5 files changed, 454 insertions, 216 deletions
diff --git a/frontend/src/components/DocShell.vue b/frontend/src/components/DocShell.vue new file mode 100644 index 0000000..ac9ef67 --- /dev/null +++ b/frontend/src/components/DocShell.vue @@ -0,0 +1,161 @@ +<!-- SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com> --> +<!-- SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1 --> + +<script setup lang="ts"> +import { computed, nextTick, onMounted, ref, watch } from "vue"; +import { RouterLink } from "vue-router"; +import { sidebarFor } from "../content/routes"; +import { locale } from "../preferences"; +import { site } from "../site"; + +/** + * The frame of every documentation page: the topics of the site on the left, the page in a readable column, the + * headings of the page on the right, and the previous and next topics under it. The headings are read from the + * rendered page, so a page only has to write its h2 elements. + */ +const props = defineProps<{ path: string; editPath: string }>(); + +const labels = { + "en-US": { + contents: "Contents", + onPage: "On this page", + previous: "Previous", + next: "Next", + edit: "Edit this page", + docs: "Documentation", + }, + "de-DE": { + contents: "Inhalt", + onPage: "Auf dieser Seite", + previous: "Zurück", + next: "Weiter", + edit: "Diese Seite bearbeiten", + docs: "Dokumentation", + }, + "ru-RU": { + contents: "Содержание", + onPage: "На этой странице", + previous: "Назад", + next: "Далее", + edit: "Изменить страницу", + docs: "Документация", + }, + "he-IL": { + contents: "תוכן", + onPage: "בעמוד הזה", + previous: "הקודם", + next: "הבא", + edit: "עריכת העמוד", + docs: "תיעוד", + }, +} as const; +const copy = computed(() => labels[locale.value]); +const brand = { language: "Tala", talac: "Talac", tazel: "Tazel" }[site]; + +const sidebar = computed(() => sidebarFor(site, locale.value)); +const position = computed(() => sidebar.value.findIndex((entry) => entry.path === props.path)); +const current = computed(() => sidebar.value[position.value]); +const previous = computed(() => + position.value > 0 ? sidebar.value[position.value - 1] : undefined, +); +const next = computed(() => + position.value >= 0 && position.value < sidebar.value.length - 1 + ? sidebar.value[position.value + 1] + : undefined, +); +const editUrl = computed( + () => `https://github.com/Progmasoft/website/blob/main/frontend/${props.editPath}`, +); + +const article = ref<HTMLElement>(); +const contents = ref<HTMLDetailsElement>(); +const headings = ref<{ id: string; text: string }[]>([]); + +/** A fragment for a heading: its words, in any script, joined by hyphens. */ +function slug(text: string): string { + return text + .toLowerCase() + .replace(/[^\p{L}\p{N}]+/gu, "-") + .replace(/^-+|-+$/g, ""); +} + +async function collectHeadings() { + await nextTick(); + const found: { id: string; text: string }[] = []; + for (const heading of article.value?.querySelectorAll("h2") ?? []) { + const text = heading.textContent?.trim() ?? ""; + if (!text) continue; + let id = slug(text) || `section-${found.length + 1}`; + while (found.some((entry) => entry.id === id)) id = `${id}-${found.length + 1}`; + heading.id = id; + found.push({ id, text }); + } + headings.value = found; +} + +onMounted(() => { + // On a narrow screen the topics fold away above the page; on a wide one they stay open beside it. + if (contents.value && window.matchMedia("(max-width: 760px)").matches) + contents.value.open = false; + collectHeadings(); +}); +watch([locale, () => props.path], collectHeadings); +</script> + +<template> + <div class="docs"> + <aside class="docs-nav"> + <details ref="contents" class="docs-nav-toggle" open> + <summary>{{ copy.contents }}</summary> + <nav :aria-label="copy.docs"> + <p class="docs-nav-site">{{ brand }}</p> + <RouterLink + v-for="entry in sidebar" + :key="entry.path" + :to="entry.path" + :aria-current="entry.path === path ? 'page' : undefined" + >{{ entry.label }}</RouterLink + > + <a v-if="site === 'language'" href="https://github.com/Progmasoft/tala/tree/main/Spec" + >Specification ↗</a + > + </nav> + </details> + </aside> + + <div class="docs-main"> + <nav class="docs-crumbs" aria-label="Breadcrumb"> + <RouterLink to="/">{{ brand }}</RouterLink> + <span aria-hidden="true">/</span> + <span>{{ copy.docs }}</span> + <template v-if="current"> + <span aria-hidden="true">/</span> + <span aria-current="page">{{ current.label }}</span> + </template> + </nav> + <article ref="article" class="doc-content"> + <slot /> + </article> + <nav class="docs-pager" :aria-label="`${copy.previous} / ${copy.next}`"> + <RouterLink v-if="previous" class="docs-pager-previous" :to="previous.path"> + <span>{{ copy.previous }}</span> + <strong>{{ previous.label }}</strong> + </RouterLink> + <RouterLink v-if="next" class="docs-pager-next" :to="next.path"> + <span>{{ copy.next }}</span> + <strong>{{ next.label }}</strong> + </RouterLink> + </nav> + <p class="docs-edit"> + <a :href="editUrl" target="_blank" rel="noopener noreferrer">{{ copy.edit }} ↗</a> + </p> + </div> + + <aside v-if="headings.length > 1" class="docs-toc"> + <p>{{ copy.onPage }}</p> + <a v-for="heading in headings" :key="heading.id" :href="`#${heading.id}`">{{ + heading.text + }}</a> + </aside> + </div> +</template> diff --git a/frontend/src/pages/DocPage.vue b/frontend/src/pages/DocPage.vue index 061acb4..7b7ec07 100644 --- a/frontend/src/pages/DocPage.vue +++ b/frontend/src/pages/DocPage.vue @@ -3,58 +3,46 @@ <script setup lang="ts"> import { computed } from "vue"; -import { RouterLink } from "vue-router"; -import { sidebarFor } from "../content/routes"; +import DocShell from "../components/DocShell.vue"; import type { DocTopic } from "../content/types"; import { locale } from "../preferences"; import { site } from "../site"; const props = defineProps<{ topic: DocTopic; path: string }>(); const page = computed(() => props.topic[locale.value]); -const sidebar = computed(() => sidebarFor(site, locale.value)); -const kicker = { language: "TALA", talac: "TALAC", tazel: "TAZEL" }[site]; +// The file a page of each site is written in, for its "Edit this page" link. +const source = { + language: "src/content/syntax.ts", + talac: "src/content/talac.ts", + tazel: "src/content/tazel.ts", +}[site]; </script> <template> - <div class="doc-layout section-wrap"> - <aside class="doc-sidebar"> - <span class="kicker">{{ kicker }}</span - ><RouterLink - v-for="entry in sidebar" - :key="entry.path" - :to="entry.path" - :aria-current="entry.path === path ? 'page' : undefined" - >{{ entry.label }}</RouterLink - ><a v-if="site === 'language'" href="https://github.com/Progmasoft/tala/tree/main/Spec" - >Specification ↗</a - > - </aside> - <article class="doc-content"> - <span class="kicker">{{ page.section }}</span> - <h1>{{ page.heading }}</h1> - <p class="doc-lead">{{ page.lead }}</p> - <template v-for="(block, index) in page.blocks" :key="index"> - <h2 v-if="block.kind === 'heading'">{{ block.text }}</h2> - <h3 v-else-if="block.kind === 'subheading'">{{ block.text }}</h3> - <p v-else-if="block.kind === 'text'">{{ block.text }}</p> - <pre - v-else-if="block.kind === 'code'" - class="doc-code" - dir="ltr" - ><code>{{ block.code }}</code></pre> - <dl v-else-if="block.kind === 'terms'" class="doc-boundaries"> - <div v-for="item in block.items" :key="item.term"> - <dt dir="ltr"> - <code>{{ item.term }}</code> - </dt> - <dd>{{ item.detail }}</dd> - </div> - </dl> - <div v-else-if="block.kind === 'note'" class="doc-note"> - <h3>{{ block.title }}</h3> - <p>{{ block.text }}</p> + <DocShell :path="path" :edit-path="source"> + <h1>{{ page.heading }}</h1> + <p class="doc-lead">{{ page.lead }}</p> + <template v-for="(block, index) in page.blocks" :key="index"> + <h2 v-if="block.kind === 'heading'">{{ block.text }}</h2> + <h3 v-else-if="block.kind === 'subheading'">{{ block.text }}</h3> + <p v-else-if="block.kind === 'text'">{{ block.text }}</p> + <pre + v-else-if="block.kind === 'code'" + class="doc-code" + dir="ltr" + ><code>{{ block.code }}</code></pre> + <dl v-else-if="block.kind === 'terms'" class="doc-boundaries"> + <div v-for="item in block.items" :key="item.term"> + <dt dir="ltr"> + <code>{{ item.term }}</code> + </dt> + <dd>{{ item.detail }}</dd> </div> - </template> - </article> - </div> + </dl> + <div v-else-if="block.kind === 'note'" class="doc-note"> + <h3>{{ block.title }}</h3> + <p>{{ block.text }}</p> + </div> + </template> + </DocShell> </template> diff --git a/frontend/src/pages/GettingStartedPage.vue b/frontend/src/pages/GettingStartedPage.vue index e526aff..d5794e7 100644 --- a/frontend/src/pages/GettingStartedPage.vue +++ b/frontend/src/pages/GettingStartedPage.vue @@ -2,6 +2,7 @@ <!-- SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1 --> <script setup lang="ts"> +import DocShell from "../components/DocShell.vue"; import { computed } from "vue"; import { RouterLink } from "vue-router"; import { arrow, locale } from "../preferences"; @@ -256,69 +257,60 @@ public class HelloWorld { </script> <template> - <div class="doc-layout section-wrap"> - <aside class="doc-sidebar"> - <span class="kicker">TALA</span - ><RouterLink to="/docs/overview">{{ c.navOverview }}</RouterLink - ><RouterLink to="/docs/getting-started" aria-current="page">{{ c.navStart }}</RouterLink - ><a href="https://github.com/Progmasoft/tala/tree/main/Spec">Specification ↗</a> - </aside> - <article class="doc-content"> - <span class="kicker">{{ c.section }}</span> - <h1>{{ c.title }}</h1> - <p class="doc-lead">{{ c.lead }}</p> - <h2>{{ c.step1 }}</h2> - <p>{{ c.step1Text }}</p> - <pre - class="doc-code" - ><code>git clone --recurse-submodules https://github.com/Progmasoft/tala.git</code></pre> - <h2>{{ c.step2 }}</h2> - <p>{{ c.step2Text }}</p> - <p>{{ c.platform }}</p> - <pre class="doc-code"><code>go run ./helpers/cmd/develop doctor</code></pre> - <h3>{{ c.bootstrap }}</h3> - <p>{{ c.toolchainHelp }}</p> - <pre class="doc-code"><code>go run ./helpers/cmd/prebuild check + <DocShell path="/docs/getting-started" edit-path="src/pages/GettingStartedPage.vue"> + <h1>{{ c.title }}</h1> + <p class="doc-lead">{{ c.lead }}</p> + <h2>{{ c.step1 }}</h2> + <p>{{ c.step1Text }}</p> + <pre + class="doc-code" + ><code>git clone --recurse-submodules https://github.com/Progmasoft/tala.git</code></pre> + <h2>{{ c.step2 }}</h2> + <p>{{ c.step2Text }}</p> + <p>{{ c.platform }}</p> + <pre class="doc-code"><code>go run ./helpers/cmd/develop doctor</code></pre> + <h3>{{ c.bootstrap }}</h3> + <p>{{ c.toolchainHelp }}</p> + <pre class="doc-code"><code>go run ./helpers/cmd/prebuild check go run ./helpers/cmd/prebuild install</code></pre> - <h2>{{ c.step3 }}</h2> - <p>{{ c.step3Text }}</p> - <pre class="doc-code"><code>go run ./helpers/cmd/develop build + <h2>{{ c.step3 }}</h2> + <p>{{ c.step3Text }}</p> + <pre class="doc-code"><code>go run ./helpers/cmd/develop build go run ./helpers/cmd/develop test</code></pre> - <h2>{{ c.step4 }}</h2> - <p>{{ c.step4Text }}</p> - <pre class="doc-code"><code>{{ hello }}</code></pre> - <h3>{{ c.fileCheck }}</h3> - <pre - class="doc-code" - ><code>talac Examples/HelloWorld/HelloWorld.tala --emit=metadata</code></pre> - <h3>{{ c.fileBuild }}</h3> - <pre - class="doc-code" - ><code>talac Examples/HelloWorld/HelloWorld.tala --entry=Examples.HelloWorld.HelloWorld</code></pre> - <p>{{ c.subset }}</p> - <h2>{{ c.step5 }}</h2> - <p>{{ c.step5Text }}</p> - <pre class="doc-code"><code>talac --help + <h2>{{ c.step4 }}</h2> + <p>{{ c.step4Text }}</p> + <pre class="doc-code"><code>{{ hello }}</code></pre> + <h3>{{ c.fileCheck }}</h3> + <pre + class="doc-code" + ><code>talac Examples/HelloWorld/HelloWorld.tala --emit=metadata</code></pre> + <h3>{{ c.fileBuild }}</h3> + <pre + class="doc-code" + ><code>talac Examples/HelloWorld/HelloWorld.tala --entry=Examples.HelloWorld.HelloWorld</code></pre> + <p>{{ c.subset }}</p> + <h2>{{ c.step5 }}</h2> + <p>{{ c.step5Text }}</p> + <pre class="doc-code"><code>talac --help tazel help</code></pre> - <div class="doc-resource-list"> - <a v-for="link in c.links" :key="link.href" :href="link.href"> - <strong>{{ link.title }} <span aria-hidden="true">↗</span></strong> - <span>{{ link.detail }}</span> - </a> - </div> - <div class="doc-note"> - <h3>{{ c.note }}</h3> - <p>{{ c.noteText }}</p> - </div> - <div class="doc-actions"> - <RouterLink class="button button-primary" to="/docs/overview" - >{{ c.more }} {{ arrow }}</RouterLink - ><a class="inline-link" href="https://github.com/Progmasoft/tala/tree/main/Spec" - >{{ c.spec }} ↗</a - ><a class="inline-link" href="https://github.com/Progmasoft/tala/tree/main/Examples" - >{{ c.examples }} ↗</a - > - </div> - </article> - </div> + <div class="doc-resource-list"> + <a v-for="link in c.links" :key="link.href" :href="link.href"> + <strong>{{ link.title }} <span aria-hidden="true">↗</span></strong> + <span>{{ link.detail }}</span> + </a> + </div> + <div class="doc-note"> + <h3>{{ c.note }}</h3> + <p>{{ c.noteText }}</p> + </div> + <div class="doc-actions"> + <RouterLink class="button button-primary" to="/docs/overview" + >{{ c.more }} {{ arrow }}</RouterLink + ><a class="inline-link" href="https://github.com/Progmasoft/tala/tree/main/Spec" + >{{ c.spec }} ↗</a + ><a class="inline-link" href="https://github.com/Progmasoft/tala/tree/main/Examples" + >{{ c.examples }} ↗</a + > + </div> + </DocShell> </template> diff --git a/frontend/src/pages/OverviewPage.vue b/frontend/src/pages/OverviewPage.vue index 2c4ccf0..4463135 100644 --- a/frontend/src/pages/OverviewPage.vue +++ b/frontend/src/pages/OverviewPage.vue @@ -2,6 +2,7 @@ <!-- SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1 --> <script setup lang="ts"> +import DocShell from "../components/DocShell.vue"; import { computed } from "vue"; import { RouterLink } from "vue-router"; import { arrow, locale } from "../preferences"; @@ -474,67 +475,58 @@ const c = computed(() => text[locale.value]); </script> <template> - <div class="doc-layout section-wrap"> - <aside class="doc-sidebar"> - <span class="kicker">TALA</span - ><RouterLink to="/docs/overview" aria-current="page">{{ c.navOverview }}</RouterLink - ><RouterLink to="/docs/getting-started">{{ c.navStart }}</RouterLink - ><a href="https://github.com/Progmasoft/tala/tree/main/Spec">Specification ↗</a> - </aside> - <article class="doc-content"> - <span class="kicker">{{ c.section }}</span> - <h1>{{ c.title }}</h1> - <p class="doc-lead">{{ c.lead }}</p> - <h2>{{ c.goals }}</h2> - <div class="doc-points"> - <section v-for="item in c.items" :key="item.title"> - <h3>{{ item.title }}</h3> - <p>{{ item.body }}</p> - </section> + <DocShell path="/docs/overview" edit-path="src/pages/OverviewPage.vue"> + <h1>{{ c.title }}</h1> + <p class="doc-lead">{{ c.lead }}</p> + <h2>{{ c.goals }}</h2> + <div class="doc-points"> + <section v-for="item in c.items" :key="item.title"> + <h3>{{ item.title }}</h3> + <p>{{ item.body }}</p> + </section> + </div> + <h2>{{ c.modelHeading }}</h2> + <p>{{ c.modelIntro }}</p> + <div class="doc-points"> + <section v-for="item in c.model" :key="item.title"> + <h3>{{ item.title }}</h3> + <p>{{ item.body }}</p> + </section> + </div> + <h2>{{ c.pipelineHeading }}</h2> + <p>{{ c.pipelineIntro }}</p> + <ol class="doc-pipeline"> + <li v-for="step in c.pipeline" :key="step.title"> + <h3>{{ step.title }}</h3> + <p>{{ step.body }}</p> + </li> + </ol> + <h2>{{ c.boundariesHeading }}</h2> + <dl class="doc-boundaries"> + <div v-for="boundary in c.boundaries" :key="boundary.label"> + <dt>{{ boundary.label }}</dt> + <dd>{{ boundary.value }}</dd> </div> - <h2>{{ c.modelHeading }}</h2> - <p>{{ c.modelIntro }}</p> - <div class="doc-points"> - <section v-for="item in c.model" :key="item.title"> - <h3>{{ item.title }}</h3> - <p>{{ item.body }}</p> - </section> + </dl> + <h2>{{ c.not }}</h2> + <p>{{ c.notText }}</p> + <h2>{{ c.questionHeading }}</h2> + <div class="doc-points"> + <section v-for="question in c.questions" :key="question.q"> + <h3>{{ question.q }}</h3> + <p>{{ question.a }}</p> + </section> + </div> + <div class="doc-next"> + <h2>{{ c.next }}</h2> + <p>{{ c.nextText }}</p> + <div class="doc-actions"> + <RouterLink class="button button-primary" to="/docs/getting-started" + >{{ c.start }} {{ arrow }}</RouterLink + ><a class="button button-quiet" href="https://github.com/Progmasoft/tala/tree/main/Spec" + >{{ c.spec }} ↗</a + ><a class="inline-link" href="https://github.com/Progmasoft/tala">{{ c.source }} ↗</a> </div> - <h2>{{ c.pipelineHeading }}</h2> - <p>{{ c.pipelineIntro }}</p> - <ol class="doc-pipeline"> - <li v-for="step in c.pipeline" :key="step.title"> - <h3>{{ step.title }}</h3> - <p>{{ step.body }}</p> - </li> - </ol> - <h2>{{ c.boundariesHeading }}</h2> - <dl class="doc-boundaries"> - <div v-for="boundary in c.boundaries" :key="boundary.label"> - <dt>{{ boundary.label }}</dt> - <dd>{{ boundary.value }}</dd> - </div> - </dl> - <h2>{{ c.not }}</h2> - <p>{{ c.notText }}</p> - <h2>{{ c.questionHeading }}</h2> - <div class="doc-points"> - <section v-for="question in c.questions" :key="question.q"> - <h3>{{ question.q }}</h3> - <p>{{ question.a }}</p> - </section> - </div> - <div class="doc-next"> - <h2>{{ c.next }}</h2> - <p>{{ c.nextText }}</p> - <div class="doc-actions"> - <RouterLink class="button button-primary" to="/docs/getting-started" - >{{ c.start }} {{ arrow }}</RouterLink - ><a class="button button-quiet" href="https://github.com/Progmasoft/tala/tree/main/Spec" - >{{ c.spec }} ↗</a - ><a class="inline-link" href="https://github.com/Progmasoft/tala">{{ c.source }} ↗</a> - </div> - </div> - </article> - </div> + </div> + </DocShell> </template> diff --git a/frontend/src/styles/site.css b/frontend/src/styles/site.css index 7695a64..0133939 100644 --- a/frontend/src/styles/site.css +++ b/frontend/src/styles/site.css @@ -105,10 +105,6 @@ p { .skip-link:focus { top: 8px; } -.section-wrap { - width: min(100% - 48px, 1050px); - margin: 0 auto; -} .site-header { display: flex; @@ -185,15 +181,6 @@ p { .inline-link:hover { text-decoration: underline; } -.kicker { - color: var(--accent); - font: - 600 11px/1.5 ui-monospace, - Consolas, - monospace; - letter-spacing: 0.08em; - text-transform: uppercase; -} .doc-actions { display: flex; align-items: center; @@ -243,33 +230,6 @@ p { Consolas, monospace; } - -.doc-layout { - display: grid; - grid-template-columns: 200px minmax(0, 760px); - gap: 60px; - padding-top: 65px; - padding-bottom: 100px; -} -.doc-sidebar { - display: flex; - flex-direction: column; - align-self: start; - gap: 16px; - position: sticky; - top: 25px; - font-size: 13px; -} -.doc-sidebar .kicker { - margin-bottom: 8px; -} -.doc-sidebar a { - color: var(--muted); -} -.doc-sidebar a[aria-current="page"], -.doc-sidebar a:hover { - color: var(--accent); -} .doc-content h1 { margin: 13px 0 21px; font-size: clamp(34px, 4vw, 48px); @@ -422,15 +382,6 @@ p { .header-tools { margin-left: auto; } - .doc-layout { - grid-template-columns: minmax(0, 1fr); - gap: 27px; - } - .doc-sidebar { - position: static; - flex-direction: row; - flex-wrap: wrap; - } .doc-boundaries div { grid-template-columns: 1fr; gap: 4px; @@ -611,3 +562,157 @@ p { display: none; } } + +/* Documentation: the topics, the page in a readable column, and its headings. */ +.docs { + display: grid; + grid-template-columns: 210px minmax(0, 720px) 190px; + justify-content: center; + gap: 48px; + width: min(100% - 48px, 1240px); + margin: 0 auto; + padding: 36px 0 72px; +} +.docs-nav-toggle > summary { + display: none; +} +.docs-nav nav { + position: sticky; + top: 24px; + display: flex; + flex-direction: column; + gap: 2px; +} +.docs-nav-site { + margin-bottom: 8px; + color: var(--text); + font-weight: 600; +} +.docs-nav a { + padding: 6px 10px; + border-radius: 7px; + color: var(--muted); + font-size: 14px; +} +.docs-nav a:hover { + background: var(--panel); + color: var(--text); +} +.docs-nav a[aria-current="page"] { + background: var(--panel); + color: var(--accent); + font-weight: 600; +} +.docs-crumbs { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 18px; + color: var(--quiet); + font-size: 13px; +} +.docs-crumbs a:hover { + color: var(--accent); +} +.docs-main .doc-content h1 { + margin-bottom: 14px; + font-size: clamp(30px, 4vw, 40px); + line-height: 1.15; +} +.docs-main .doc-content h2 { + scroll-margin-top: 20px; +} +.docs-pager { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 16px; + margin-top: 48px; + padding-top: 24px; + border-top: 1px solid var(--border); +} +.docs-pager a { + display: flex; + flex-direction: column; + gap: 4px; + padding: 14px 16px; + border: 1px solid var(--border); + border-radius: 10px; +} +.docs-pager a:hover { + border-color: var(--accent); +} +.docs-pager span { + color: var(--quiet); + font-size: 13px; +} +.docs-pager-next { + grid-column: 2; + text-align: end; +} +.docs-edit { + margin-top: 18px; + font-size: 13px; +} +.docs-edit a { + color: var(--quiet); +} +.docs-edit a:hover { + color: var(--accent); +} +.docs-toc { + position: sticky; + top: 24px; + align-self: start; + display: flex; + flex-direction: column; + gap: 8px; + font-size: 13px; +} +.docs-toc p { + margin-bottom: 4px; + color: var(--text); + font-weight: 600; +} +.docs-toc a { + color: var(--muted); + line-height: 1.4; +} +.docs-toc a:hover { + color: var(--accent); +} +@media (max-width: 1100px) { + .docs { + grid-template-columns: 200px minmax(0, 1fr); + } + .docs-toc { + display: none; + } +} +@media (max-width: 760px) { + .docs { + grid-template-columns: minmax(0, 1fr); + gap: 20px; + width: calc(100% - 32px); + padding-top: 20px; + } + .docs-nav-toggle { + border: 1px solid var(--border); + border-radius: 10px; + } + .docs-nav-toggle > summary { + display: block; + padding: 10px 14px; + cursor: pointer; + font-weight: 600; + } + .docs-nav nav { + position: static; + padding: 0 8px 10px; + } + .docs-pager { + grid-template-columns: 1fr; + } + .docs-pager-next { + grid-column: 1; + } +} |