diff --git a/packages/docs/src/app/(docs)/layout.tsx b/packages/docs/src/app/(docs)/layout.tsx index 0c2d98d..3198081 100644 --- a/packages/docs/src/app/(docs)/layout.tsx +++ b/packages/docs/src/app/(docs)/layout.tsx @@ -7,7 +7,6 @@ export default function Layout({ children }: { children: ReactNode }) { return ( }} searchToggle={{ enabled: false }} themeSwitch={{ enabled: false }} diff --git a/packages/docs/src/app/global.css b/packages/docs/src/app/global.css index fb652c1..544ca82 100644 --- a/packages/docs/src/app/global.css +++ b/packages/docs/src/app/global.css @@ -7,6 +7,10 @@ @source "../../node_modules/fumadocs-ui/dist/**/*.js"; @source "../../node_modules/fumadocs-ui/css/**/*.css"; +html { + overflow-x: hidden; +} + /* --- Layout --- */ @media (min-width: 768px) { @@ -16,7 +20,7 @@ } #nd-docs-layout { - --fd-layout-width: 100vw; + --fd-layout-width: 100%; } #nd-page > .prose { @@ -30,6 +34,34 @@ color: rgb(var(--color-magenta)) !important; } +/* --- Docs mobile sidebar trigger --- + The DocsLayout sub-header (#nd-subnav, md:hidden) contains the sidebar + drawer toggle. Strip the bar chrome and float the button below the nav. */ + +#nd-subnav { + position: fixed; + top: auto; + bottom: 1rem; + right: 1rem; + left: auto; + width: auto; + height: auto; + border: 1px solid rgb(var(--color-border)); + border-radius: 10px; + background: rgb(var(--color-surface)); + padding: 0; + z-index: 35; + box-shadow: 0 2px 12px rgb(0 0 0 / 0.25); +} + +#nd-subnav > :not(button) { + display: none; +} + +#nd-subnav > button { + padding: 0.625rem; +} + /* --- Sidebar --- */ @media (min-width: 768px) { @@ -173,6 +205,13 @@ #nd-home-layout { background: transparent; + max-width: 100%; + overflow-x: clip; +} + +#nd-home-layout > * { + min-width: 0; + width: 100%; } #nd-home-layout article > canvas { diff --git a/packages/docs/src/components/vaporwave-grid.tsx b/packages/docs/src/components/vaporwave-grid.tsx index 8fe228f..c1f1229 100644 --- a/packages/docs/src/components/vaporwave-grid.tsx +++ b/packages/docs/src/components/vaporwave-grid.tsx @@ -27,9 +27,14 @@ export function VaporwaveGrid() { function resize() { const dpr = window.devicePixelRatio || 1; - const rect = canvas!.getBoundingClientRect(); - w = rect.width; - h = rect.height; + const vw = window.innerWidth; + canvas!.style.width = ''; + canvas!.style.marginLeft = ''; + const canvasLeft = canvas!.getBoundingClientRect().left; + canvas!.style.width = `${vw}px`; + canvas!.style.marginLeft = `${-canvasLeft}px`; + w = vw; + h = canvas!.getBoundingClientRect().height; canvas!.width = w * dpr; canvas!.height = h * dpr; ctx!.setTransform(dpr, 0, 0, dpr, 0, 0); @@ -215,21 +220,28 @@ export function VaporwaveGrid() { if (reducedMotion) { const drawStatic = () => render({ elapsed: 0, faceReveal: 1, scrollOffset: 0, glitch: false }); - const observer = new ResizeObserver(() => { resize(); drawStatic(); }); + const onResize = () => { resize(); drawStatic(); }; + const observer = new ResizeObserver(onResize); observer.observe(canvas); + window.addEventListener('resize', onResize); drawStatic(); if (!logo.complete || logo.naturalWidth === 0) { logo.addEventListener('load', drawStatic, { once: true }); return () => { logo.removeEventListener('load', drawStatic); + window.removeEventListener('resize', onResize); observer.disconnect(); }; } - return () => observer.disconnect(); + return () => { + window.removeEventListener('resize', onResize); + observer.disconnect(); + }; } const observer = new ResizeObserver(resize); observer.observe(canvas); + window.addEventListener('resize', resize); function draw(time: number) { const elapsed = time / 1000; @@ -250,6 +262,7 @@ export function VaporwaveGrid() { return () => { cancelAnimationFrame(animationId); + window.removeEventListener('resize', resize); observer.disconnect(); }; }, [reducedMotion]); @@ -261,8 +274,6 @@ export function VaporwaveGrid() { className="not-prose" style={{ display: 'block', - width: '100vw', - marginLeft: 'calc(-50vw + 50%)', height: '100vh', marginTop: '-60vh', position: reducedMotion ? 'relative' : 'sticky',