T45a Site · Stack: Vite 8, React 19 and TanStack Router under pnpm; routes, theme, fonts, the manifest

This commit is contained in:
ZacharyZhang-NY committed 2026-10-01 08:38:05 -04:00
1 parent e3957f7816
commit 167055fdae
32 files changed
+699 -1309

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
import { Link } from "@tanstack/react-router";
import { useEffect } from "react";
import { chapters, pad } from "../data";
export function Chapters() {
useEffect(() => {
document.title = "Components · Ely";
}, []);
return (
<section className="chapters">
<h1>Components</h1>
<ol>
{chapters.map((c) => (
<li key={c.slug}>
<Link to="/components/$page/$story/" params={{ page: c.slug, story: c.stories[0].slug }}>
<span className="n">{pad(c.number)}</span>
<span className="name">{c.title}</span>
<span className="count">{c.stories.length}</span>
</Link>
</li>
))}
</ol>
</section>
);
}
+20
View File
@@ -0,0 +1,20 @@
import { Link } from "@tanstack/react-router";
import { useEffect } from "react";
import { chapters, componentCount } from "../data";
export function Home() {
useEffect(() => {
document.title = "Ely · GPUI components";
}, []);
return (
<section className="hero">
<h1>Components for GPUI.</h1>
<p>
{componentCount} components in {chapters.length} chapters, live in the browser.
</p>
<Link to="/components/" className="button">
Browse
</Link>
</section>
);
}
+18
View File
@@ -0,0 +1,18 @@
import { Link } from "@tanstack/react-router";
import { useEffect } from "react";
export function NotFound({ what = "Nothing lives at this address." }: { what?: string }) {
useEffect(() => {
console.error(`site: ${what} (${location.pathname})`);
document.title = "Not found · Ely";
}, [what]);
return (
<section className="missing">
<h1>Not found</h1>
<p>{what}</p>
<Link to="/components/" className="button">
All components
</Link>
</section>
);
}
+46
View File
@@ -0,0 +1,46 @@
import { Link, useParams } from "@tanstack/react-router";
import { useEffect } from "react";
import { Live } from "../Live";
import { Capture, Windows, isCaptured } from "../Native";
import { all, chapters } from "../data";
import { NotFound } from "./NotFound";
export function Story() {
const { page, story } = useParams({ strict: false });
const chapter = chapters.find((c) => c.slug === page);
const found = chapter?.stories.find((s) => s.slug === story);
useEffect(() => {
if (chapter && found) document.title = `${found.title} · ${chapter.title} · Ely`;
}, [chapter, found]);
if (!chapter || !found) return <NotFound what={`No story at ${page}/${story}.`} />;
const at = all.findIndex((e) => e.story === found);
const [prev, next] = [all[at - 1], all[at + 1]];
return (
<article className="story">
<Link to="/components/" className="crumb">
{chapter.title}
</Link>
<h1>{found.title}</h1>
{isCaptured(chapter.slug, found.slug) ? (
<Capture page={chapter.slug} story={found.slug} title={found.title} />
) : (
<>
<Live key={`${chapter.slug}/${found.slug}`} page={chapter.slug} story={found.slug} title={found.title} />
<Windows page={chapter.slug} story={found.slug} title={found.title} />
</>
)}
<nav className="pager" aria-label="More stories">
{prev && (
<Link to="/components/$page/$story/" params={{ page: prev.chapter.slug, story: prev.story.slug }}>
{prev.story.title}
</Link>
)}
{next && (
<Link className="next" to="/components/$page/$story/" params={{ page: next.chapter.slug, story: next.story.slug }}>
{next.story.title}
</Link>
)}
</nav>
</article>
);
}