docs: README for the blueprint structure; drop standalone-UI sections

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 19:07:36 +02:00
parent 899028e20f
commit e6144773d7
22 changed files with 34 additions and 3131 deletions
-82
View File
@@ -1,82 +0,0 @@
import { Gamepad2 } from "lucide-react";
import { useEffect, useState } from "react";
import { cn } from "./lib/utils.js";
import { Emulators } from "./pages/Emulators.js";
import { Games } from "./pages/Games.js";
import { Setup } from "./pages/Setup.js";
import { Sync } from "./pages/Sync.js";
const TABS = [
{ id: "setup", label: "Setup", Page: Setup },
{ id: "emulators", label: "Emulators", Page: Emulators },
{ id: "games", label: "Games", Page: Games },
{ id: "sync", label: "Sync", Page: Sync },
] as const;
type TabId = (typeof TABS)[number]["id"];
const tabFromHash = (): TabId => {
const h = window.location.hash.replace(/^#\/?/, "");
return (TABS.find((t) => t.id === h)?.id ?? "setup") as TabId;
};
export const App = () => {
const [tab, setTab] = useState<TabId>(tabFromHash);
useEffect(() => {
const onHash = () => setTab(tabFromHash());
window.addEventListener("hashchange", onHash);
return () => window.removeEventListener("hashchange", onHash);
}, []);
const go = (id: TabId) => {
window.location.hash = `/${id}`;
setTab(id);
// Best-effort deep-link sync with the console shell (plugin-ui-surface §5; ignored elsewhere).
try {
window.parent?.postMessage({ type: "pf-ui:navigate", path: id }, "*");
} catch {
// not embedded
}
};
const Page = TABS.find((t) => t.id === tab)?.Page ?? Setup;
return (
<div className="mx-auto max-w-5xl px-6 pb-16 pt-6">
<header className="flex items-center gap-3">
<span className="grid size-9 place-items-center rounded-card bg-primary/15 text-primary">
<Gamepad2 className="size-5" />
</span>
<div>
<h1 className="text-lg font-semibold leading-tight">ROM Manager</h1>
<p className="text-sm text-muted-foreground">
Scan ROMs into your Punktfunk library
</p>
</div>
</header>
<nav className="mt-6 flex flex-wrap gap-1 border-b border-border">
{TABS.map((t) => (
<button
type="button"
key={t.id}
onClick={() => go(t.id)}
className={cn(
"-mb-px border-b-2 px-4 py-2 text-sm font-medium transition-colors",
t.id === tab
? "border-primary text-foreground"
: "border-transparent text-muted-foreground hover:text-foreground",
)}
>
{t.label}
</button>
))}
</nav>
<main className="mt-6 flex flex-col gap-6">
<Page />
</main>
</div>
);
};