diff --git a/packages/web/src/App.svelte b/packages/web/src/App.svelte index 557a721..45e7555 100644 --- a/packages/web/src/App.svelte +++ b/packages/web/src/App.svelte @@ -9,6 +9,7 @@ import Faq from "./Faq.svelte"; import Card from "./Card.svelte"; import Help from "./Help.svelte"; + import type { HelpTab } from "./help-state"; import Replay from "./Replay.svelte"; import FxGallery from "./FxGallery.svelte"; import TokenGallery from "./TokenGallery.svelte"; @@ -257,7 +258,39 @@ let faqCardId = $state(null); /** A discard-pile card enlarged above the pile. */ let discardPeek = $state(null); - let helpTab = $state<"play" | "rules" | "cards" | "rulings" | "about" | "tally">("play"); + /** The help's opening tab; null reopens it where the reader left off. */ + let helpTab = $state(null); + let helpAnchor = $state(null); + let helpCard = $state(null); + // A link into the reference β€” /?help=rules/rulebook-line-of-sight or + // /?card=force-field β€” opens the desk to that page. + { + const q = new URLSearchParams(location.search); + const card = q.get("card"); + const help = q.get("help"); + const tabs: HelpTab[] = ["play", "rules", "cards", "rulings", "about", "tally"]; + if (card) { helpCard = card; showHelp = true; } + else if (help) { + const [t, ...rest] = help.split("/"); + if (tabs.includes(t as HelpTab)) { helpTab = t as HelpTab; helpAnchor = rest.join("/") || null; showHelp = true; } + } + } + /** The address bar follows the reader through the help, so any page is a link. */ + function helpNavigate(tab: HelpTab, anchor: string | null, card: string | null) { + const u = new URL(location.href); + u.searchParams.delete("help"); u.searchParams.delete("card"); + if (card) u.searchParams.set("card", card); + else u.searchParams.set("help", anchor ? `${tab}/${anchor}` : tab); + // The slash stays a slash: /?help=rules/the-cards reads as a path should. + u.search = u.searchParams.toString().replace(/%2F/g, "/"); + history.replaceState(null, "", u); + } + function helpClose() { + showHelp = false; helpAnchor = null; helpCard = null; helpTab = null; + const u = new URL(location.href); + u.searchParams.delete("help"); u.searchParams.delete("card"); + history.replaceState(null, "", u); + } let hotseatCount = $state(2); let setupName = $state(""); let setupColor = $state(0); @@ -1695,7 +1728,7 @@ {/if} - @@ -1969,7 +2002,8 @@ {/if} {#if showHelp} - net.requestStats()} onclose={() => (showHelp = false)} /> + net.requestStats()} onnavigate={helpNavigate} onclose={helpClose} /> {/if} {#if view?.phase === "finished" && view.winner && victoryCurtain && !victorySeen} diff --git a/packages/web/src/Help.svelte b/packages/web/src/Help.svelte index f1ff169..ea97ca0 100644 --- a/packages/web/src/Help.svelte +++ b/packages/web/src/Help.svelte @@ -1,130 +1,231 @@ -{#if libPeek} -
(libPeek = null)} onkeydown={() => {}}> -
- (faqCardId = id)} /> +{#if entryDef} + {/if} -{#if faqCardId} - (faqCardId = null)} /> -{/if} - -
{}}> -