cloudflare/kumo
Publicmirrored fromhttps://github.com/cloudflare/kumoAvailable
packages/kumo-docs-astro/src/layouts/MainLayout.astro
72lines · modecode
| 1 | --- |
| 2 | import BaseLayout from "./BaseLayout.astro"; |
| 3 | import { SidebarNav } from "../components/SidebarNav"; |
| 4 | import { ThemeToggle } from "../components/ThemeToggle"; |
| 5 | |
| 6 | interface Props { |
| 7 | title?: string; |
| 8 | description?: string; |
| 9 | } |
| 10 | |
| 11 | const { title, description } = Astro.props; |
| 12 | const currentPath = Astro.url.pathname; |
| 13 | --- |
| 14 | |
| 15 | <BaseLayout title={title} description={description}> |
| 16 | <div class="isolate"> |
| 17 | <SidebarNav currentPath={currentPath} client:load /> |
| 18 | |
| 19 | <script is:inline> |
| 20 | (function () { |
| 21 | const KEY = "kumo-sidebar-scroll"; |
| 22 | function restore() { |
| 23 | try { |
| 24 | const raw = sessionStorage.getItem(KEY); |
| 25 | if (!raw) return; |
| 26 | const pos = Number.parseInt(raw, 10); |
| 27 | if (!Number.isFinite(pos)) return; |
| 28 | const els = document.querySelectorAll("[data-sidebar-scroll]"); |
| 29 | for (const el of els) { |
| 30 | el.scrollTop = pos; |
| 31 | } |
| 32 | } catch { |
| 33 | // no-op |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | restore(); |
| 38 | window.addEventListener("astro:after-swap", restore); |
| 39 | })(); |
| 40 | </script> |
| 41 | |
| 42 | <!-- Theme toggle: fixed in top right corner --> |
| 43 | <div |
| 44 | class="pointer-events-auto fixed top-0 right-2 z-50 flex h-[49px] items-center" |
| 45 | > |
| 46 | <ThemeToggle client:only="react" /> |
| 47 | </div> |
| 48 | |
| 49 | <!-- Main content area - margin controlled by CSS :has() based on sidebar state --> |
| 50 | <div |
| 51 | id="main-content" |
| 52 | class="main-content mt-[49px] md:mt-0 md:ml-12 h-screen overflow-y-auto overscroll-y-none transition-[margin] duration-300" |
| 53 | > |
| 54 | <slot /> |
| 55 | </div> |
| 56 | </div> |
| 57 | </BaseLayout> |
| 58 | |
| 59 | <style is:global> |
| 60 | /* Use CSS :has() to detect sidebar state and adjust main content margin */ |
| 61 | @media (min-width: 768px) { |
| 62 | /* When sidebar is open, add full margin */ |
| 63 | body:has(aside[data-sidebar-open="true"]) .main-content { |
| 64 | margin-left: 304px; /* 48px rail + 256px sidebar panel */ |
| 65 | } |
| 66 | |
| 67 | /* When sidebar is closed, only rail margin */ |
| 68 | body:has(aside[data-sidebar-open="false"]) .main-content { |
| 69 | margin-left: 48px; /* w-12 = 3rem = 48px */ |
| 70 | } |
| 71 | } |
| 72 | </style> |
| 73 | |