diff --git a/src/components/docs/CopyCodeButton.astro b/src/components/docs/CopyCodeButton.astro new file mode 100644 index 0000000..c3fc92d --- /dev/null +++ b/src/components/docs/CopyCodeButton.astro @@ -0,0 +1,134 @@ +--- +/** + * CopyCodeButton - framework-free "copy to clipboard" affordance for inline + * CDL/code snippets. + * + * Renders a small icon button that copies its `code` prop to the clipboard + * and swaps to a checkmark + "Copied" state briefly on success. Follows the + * same pattern as ThemeToggle.astro: a single delegated click listener bound + * once per page (guarded by a `window` flag), so this can be rendered dozens + * of times on one page (e.g. one per example card) without adding dozens of + * listeners. + */ +interface Props { + code: string; + label?: string; + class?: string; +} + +const { code, label = 'Copy CDL to clipboard', class: className = '' } = Astro.props; +--- + + + + + + diff --git a/src/components/docs/DocsLayout.astro b/src/components/docs/DocsLayout.astro new file mode 100644 index 0000000..7011a5a --- /dev/null +++ b/src/components/docs/DocsLayout.astro @@ -0,0 +1,93 @@ +--- +/** + * DocsLayout - shared chrome for every page under `/docs`. + * + * Wraps `BaseLayout` and adds the persistent `DocsSidebar`, an automatic + * `Breadcrumb` + `PageNav` (both derived from the single nav tree in + * `src/lib/docs/nav.ts` for the current `Astro.url.pathname`), and + * optionally `DocsTOC` for long reference pages. + * + * Usage - replace a page's `` + + * its own ``/``/`` with: + * + * + *
...page content, unchanged...
+ *
+ * + * Pass `showToc` for the long reference pages (CDL spec, CLI options, + * Components, the 4 API pages) to render `DocsTOC` in a third rail at xl+. + * Pass `wide` for pages whose content is a card grid / component gallery + * rather than a prose article (index, components) so the content column + * isn't capped to reading width. + * + * Layout/responsive approach: + * - Mobile (` + * disclosure inline above the content; `DocsTOC` (if present) renders + * its own floating button + bottom sheet, independent of scroll + * position. + * - lg+: two-column CSS grid, `[240px_minmax(0,1fr)]` - sidebar rail then + * content. Both the sidebar's and (at xl+, see below) the TOC's grid + * cells get `lg:self-stretch`/`xl:self-stretch` so the cell spans the + * full row height. This is required for `position: sticky` to have any + * travel room - a cell that shrink-wraps its sticky child's own height + * gives the sticky rule nothing to do, which was the exact bug just + * fixed on `/learn`. Verified by measuring the sidebar's + * `getBoundingClientRect()` after a ~1500px scroll (see verification + * notes in the PR/commit for this change). + * - xl+ (only when `showToc`): a third `240px` column is added for + * `DocsTOC`, so long pages become sidebar | content | TOC. + */ +import BaseLayout from '../../layouts/BaseLayout.astro'; +import DocsSidebar from './DocsSidebar.astro'; +import DocsTOC from './DocsTOC.astro'; +import Breadcrumb from './Breadcrumb.astro'; +import PageNav from './PageNav.astro'; +import { Container } from '../ui-astro'; +import { getDocsBreadcrumb, getDocsPageNav } from '../../lib/docs/nav'; + +interface Props { + title: string; + description?: string; + /** Render the in-page "On this page" TOC rail (long reference pages only). */ + showToc?: boolean; + /** Card-grid/gallery pages that want the full content-column width instead of a reading-width cap. */ + wide?: boolean; +} + +const { title, description, showToc = false, wide = false } = Astro.props; + +const pathname = Astro.url.pathname; +const breadcrumbItems = getDocsBreadcrumb(pathname); +const { prev, next } = getDocsPageNav(pathname); +--- + + + +
+
+ +
+ +
+ {breadcrumbItems && } + +
+ +
+ + +
+ + {showToc && ( + + )} +
+
+
diff --git a/src/components/docs/DocsSidebar.astro b/src/components/docs/DocsSidebar.astro new file mode 100644 index 0000000..c35bfe4 --- /dev/null +++ b/src/components/docs/DocsSidebar.astro @@ -0,0 +1,113 @@ +--- +/** + * DocsSidebar - persistent cross-page navigation for the /docs section. + * + * Renders the grouped nav tree from `src/lib/docs/nav.ts` (single source of + * truth, shared with the flat prev/next ordering and breadcrumb lookup). + * + * Two variants, each responsible for hiding itself at the "wrong" breakpoint + * (mirrors the pattern in `src/components/learn/TableOfContents.astro`): + * - Mobile (` "Documentation menu" disclosure sitting + * inline at the top of the content column. A `
` (rather than + * the floating-button+dialog pattern also used on this site for + * `DocsTOC`) was chosen deliberately: this is a full page tree, not a + * handful of in-page anchors, and long docs pages already get a floating + * "On this page" button from `DocsTOC` — a second floating trigger on + * the same screen would be redundant and visually competing. A simple + * inline disclosure avoids that collision entirely. + * - Desktop (lg+): a sticky aside rail. `DocsLayout.astro` places this + * component's wrapper in a grid cell with `lg:self-stretch` so the cell + * spans the full row height - without that, `position: sticky` has no + * room to travel and the rail scrolls off with the page (the bug fixed + * in `learn/TableOfContents.astro`; do not reintroduce it here). + */ +import { docsNav, isDocsNavActive } from '../../lib/docs/nav'; + +const pathname = Astro.url.pathname; +--- + + +
+ + + + Documentation menu + + + + +
+ + + + + diff --git a/src/components/docs/DocsTOC.astro b/src/components/docs/DocsTOC.astro new file mode 100644 index 0000000..8e1f0e6 --- /dev/null +++ b/src/components/docs/DocsTOC.astro @@ -0,0 +1,365 @@ +--- +/** + * DocsTOC - "On this page" navigation for long, hand-authored docs pages. + * + * Unlike `learn/TableOfContents.astro` (which receives structured `sections` + * data as a prop), docs pages are plain `.astro` files with hand-written + * `

`/`

` headings and no shared content schema. So this component + * builds its list entirely client-side: a script scans `contentSelector` + * for headings, assigns a stable slug id to any heading missing one, and + * renders the list + scroll-spy from that scan. There is no server-rendered + * fallback list - see the "why no build-time list" note in the script below. + * + * Rendered only by `DocsLayout.astro` when `showToc` is true (the long + * reference pages: CDL spec, CLI options, Components, and the 4 API pages). + * + * Mirrors the two-variant responsive split used by `learn/TableOfContents.astro`: + * - Desktop (lg+): sticky right rail with scroll-spy. + * - Mobile (` + * bottom sheet. This is deliberately the *same* mobile pattern as the + * learn TOC (not the `
` pattern `DocsSidebar` uses for the docs + * nav tree) — the two mobile controls serve different purposes (jump to + * a heading vs. cross-page navigation) and don't overlap on screen, so + * reusing the proven learn pattern here keeps mobile TOC behaviour + * consistent across the whole site. + * + * Both variants are hidden (via a shared `.docs-toc-root` wrapper) until the + * scan finds at least 2 headings, so pages with too few headings to be worth + * a TOC render nothing. + * + * `#docs-toc-root` carries `xl:h-full` deliberately: unlike `DocsSidebar` + * (whose top-level elements are the `
`/`