5et Initial React Skin

This commit is contained in:
boris committed 2026-02-24 19:58:53 +00:00
1 parent b236390afe
commit 0eb340e1c2
17 files changed
+5079

No files matched your search

+91
View File
@@ -0,0 +1,91 @@
import { useEffect, useMemo, useState } from "react";
import { WIKI_NAV_SECTIONS } from "./wikiNav";
const DEFAULT_PAGE = "/5etools.html";
export default function App() {
const [wikiUrl, setWikiUrl] = useState<string>("");
const [error, setError] = useState<string>("");
const [currentPath, setCurrentPath] = useState<string>(DEFAULT_PAGE);
useEffect(() => {
window.desktopApi
.getWikiUrl()
.then((url) => setWikiUrl(url))
.catch((err: unknown) => {
const message = err instanceof Error ? err.message : "Unknown error";
setError(message);
});
}, []);
const frameSrc = useMemo(() => {
if (!wikiUrl) {
return "";
}
return new URL(currentPath, `${wikiUrl}/`).toString();
}, [currentPath, wikiUrl]);
if (error) {
return (
<main className="status-wrap">
<section className="status-panel">
<h1>5etools Desktop failed to start</h1>
<p>{error}</p>
</section>
</main>
);
}
if (!wikiUrl) {
return (
<main className="status-wrap">
<section className="status-panel">
<h1>Starting 5etools Desktop</h1>
<p>Loading local 5etools wiki...</p>
</section>
</main>
);
}
return (
<main className="shell" aria-label="5etools Desktop Wiki Shell">
<aside className="sidebar">
<header className="sidebar-brand">
<p className="sidebar-kicker">5etools Desktop</p>
<h1 className="sidebar-title">Compendium</h1>
<p className="sidebar-copy">5etools Desktop by <b>notBoris</b>.</p>
<p className="sidebar-copy-subtitle">This application is not affiliated with the 5etools Project. 5etools® is a Registered Trademark of The Norr Group Ltd. All rights reserved.</p>
</header>
<nav className="sidebar-nav" aria-label="Wiki Sections">
{WIKI_NAV_SECTIONS.map((section) => (
<section key={section.title} className="nav-section">
<h2>{section.title}</h2>
<ul>
{section.items.map((item) => (
<li key={item.path}>
<button
type="button"
className={item.path === currentPath ? "nav-item is-active" : "nav-item"}
onClick={() => setCurrentPath(item.path)}
>
<span className="nav-item-label">{item.label}</span>
<span className="nav-item-desc">{item.description}</span>
</button>
</li>
))}
</ul>
</section>
))}
</nav>
</aside>
<section className="workspace">
<section className="frame-shell frame-shell--full">
<iframe className="wiki-frame" src={frameSrc} title="5etools Wiki" />
</section>
</section>
</main>
);
}