diff --git a/apps/site/index.html b/apps/site/index.html index 7062b2d..c53943e 100644 --- a/apps/site/index.html +++ b/apps/site/index.html @@ -3,17 +3,71 @@ + + + Visimer · Edit Mermaid diagrams by hand + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/apps/site/public/favicon.svg b/apps/site/public/favicon.svg new file mode 100644 index 0000000..7fe624d --- /dev/null +++ b/apps/site/public/favicon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/apps/site/public/og-image.png b/apps/site/public/og-image.png new file mode 100644 index 0000000..244d13a Binary files /dev/null and b/apps/site/public/og-image.png differ diff --git a/apps/site/public/robots.txt b/apps/site/public/robots.txt new file mode 100644 index 0000000..6000662 --- /dev/null +++ b/apps/site/public/robots.txt @@ -0,0 +1,4 @@ +User-agent: * +Allow: / + +Sitemap: https://visimer.com/sitemap.xml diff --git a/apps/site/public/sitemap.xml b/apps/site/public/sitemap.xml new file mode 100644 index 0000000..d528d5d --- /dev/null +++ b/apps/site/public/sitemap.xml @@ -0,0 +1,8 @@ + + + + https://visimer.com/ + weekly + 1.0 + + diff --git a/apps/site/src/App.tsx b/apps/site/src/App.tsx index 817698f..f068ebd 100644 --- a/apps/site/src/App.tsx +++ b/apps/site/src/App.tsx @@ -276,14 +276,22 @@ export default function App() { const badge = badgeRef.current if (!badge) return const navBottom = 80 - const startTop = badge.getBoundingClientRect().top + window.scrollY - navBottom - const onScroll = () => { - const distance = badge.getBoundingClientRect().top - navBottom - setStarHintOpacity(Math.max(0, Math.min(1, distance / startTop))) + const compute = () => { + const rect = badge.getBoundingClientRect() + // Re-derive the fade origin every tick so a late web-font layout + // shift or viewport resize doesn't leave the ratio stale. + const startTop = rect.top + window.scrollY - navBottom + if (startTop <= 0) return 0 + return Math.max(0, Math.min(1, (rect.top - navBottom) / startTop)) } + const onScroll = () => setStarHintOpacity(compute()) onScroll() window.addEventListener('scroll', onScroll, { passive: true }) - return () => window.removeEventListener('scroll', onScroll) + window.addEventListener('resize', onScroll, { passive: true }) + return () => { + window.removeEventListener('scroll', onScroll) + window.removeEventListener('resize', onScroll) + } }, []) const switchType = (next: string) => { @@ -541,7 +549,16 @@ export default function App() { href="#demo" onClick={(e) => { e.preventDefault() - document.getElementById('demo')?.scrollIntoView({ behavior: 'smooth' }) + // Park the page at the demo section BEFORE expanding, so that + // when the user exits fullscreen they land on the playground + // instead of back at the hero. scrollTo is synchronous; + // scrollIntoView({smooth}) would be frozen mid-animation by + // the body.overflow=hidden expand triggers. + const demo = document.getElementById('demo') + // `behavior: 'instant'` overrides the html { scroll-behavior: + // smooth } rule; a smooth scroll here gets frozen mid-way by + // the body.overflow=hidden the useEffect triggers on expand. + if (demo) window.scrollTo({ top: demo.offsetTop - 20, behavior: 'instant' }) setExpandedAnimated(true) }} style={{