feat(tour): a welcome of its own, the owner's order, and the way to codes

The tour opens on a welcome over the dimmed Checklist, then shows the bar
along the top, then the Checklist and Timeline with their looks, Routines,
Archive and Settings. Codes get three steps that walk the way in (the game
in Settings, its Codes tab, the codes), and the last step points at Replay
the introduction. A replay now dims and locks the page like the first run,
keeping only Close tour. Subjects out of sight scroll into view, and the
ring stays inside the window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas WintherandClaude Opus 5.5 committed 2026-10-18 05:27:02 +02:00
1 parent 83ed9fa3fa
commit 874d8627a2
7 files changed
+171 -84

No files matched your search

+23 -13
View File
@@ -691,10 +691,10 @@ function ReaderContent({
className="app-shell reader-ui"
data-touring={touring || undefined}
>
{/* While the tour is forced the page behind shows each stop but
takes no clicks or focus. `display: contents` keeps the layout
as if this wrapper were not here. */}
<div className="tour-behind" inert={tourForced}>
{/* During the tour, forced or replayed, the page behind shows each
stop but takes no clicks or focus. `display: contents` keeps the
layout as if this wrapper were not here. */}
<div className="tour-behind" inert={touring}>
<header className="top">
{prefs.onboarded ? (
<button
@@ -1150,21 +1150,31 @@ function ReaderContent({
onStep={(stop) => {
setOpen(null);
setArchivedOpen(null);
if (stop !== "codes") {
if (stop === "settings") showSettings("appearance");
else setPage(stop);
if (stop === "settings" || stop === "replay") {
setCodesGame(undefined);
showSettings("appearance");
return;
}
// The Codes tab of a tracked game that has codes, else the
// Checklist, where new codes are announced.
const game = accounts
.map((a) => a.game)
.find((g) => codes?.codes.some((c) => c.game === g));
if (
stop !== "codes-game" &&
stop !== "codes-tab" &&
stop !== "codes"
) {
setPage(stop);
return;
}
// A tracked game that has codes, else any tracked game:
// its Codes tab says when none are published.
const game =
accounts
.map((a) => a.game)
.find((g) => codes?.codes.some((c) => c.game === g)) ??
accounts[0]?.game;
if (!game) {
setPage("soon");
return;
}
setGameTab("codes");
setGameTab(stop === "codes" ? "codes" : "setup");
setCodesGame(game);
showSettings("games");
}}