feat(dashboard): always-visible Tour button — replay welcome modal any time

The 10-step welcome tour was first-run-only (persisted in IndexedDB).
After dismissing, users had no clear path back to it.

Fix:
- Topbar gets a '★ Tour' ghost button next to '?' that fires
  CustomEvent('nv-show-tour') any time.
- Help-center Quickstart adds a primary 'Take the interactive 10-step
  tour' button that closes help and launches the tour.
- nv-help listens for 'nv-show-help-close' to support the help→tour
  hand-off cleanly.

Settings drawer already has 'Replay welcome tour' (added earlier);
this just makes the same action one-click from the always-visible
topbar.

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv 2026-04-27 11:40:37 -04:00
parent cedb28db83
commit f25b82ddb5
2 changed files with 13 additions and 0 deletions

View File

@ -290,13 +290,16 @@ export class NvHelp extends LitElement {
override connectedCallback(): void {
super.connectedCallback();
window.addEventListener('nv-show-help', this.show as EventListener);
window.addEventListener('nv-show-help-close', this.closeListener);
window.addEventListener('keydown', this.onKey);
}
override disconnectedCallback(): void {
super.disconnectedCallback();
window.removeEventListener('nv-show-help', this.show as EventListener);
window.removeEventListener('nv-show-help-close', this.closeListener);
window.removeEventListener('keydown', this.onKey);
}
private closeListener = (): void => this.close();
private show = (e: Event): void => {
const detail = (e as CustomEvent).detail as { section?: Section } | undefined;
@ -331,6 +334,11 @@ export class NvHelp extends LitElement {
return html`
<h2>Quickstart</h2>
<p class="lead">Seven taps to get from "I just opened the dashboard" to "I'm running my own scene with verified determinism."</p>
<button
style="display:inline-flex; align-items:center; gap:8px; padding:10px 16px; margin-bottom:14px; background:var(--accent); color:#1a0f00; border:none; border-radius:8px; font-size:13px; font-weight:600; cursor:pointer; font-family:inherit;"
@click=${() => { window.dispatchEvent(new CustomEvent('nv-show-help-close')); window.dispatchEvent(new CustomEvent('nv-show-tour')); }}>
Take the interactive 10-step tour
</button>
${QUICKSTART.map((s) => html`
<div class="step">
<div class="num">${s.step}</div>

View File

@ -117,6 +117,11 @@ export class NvTopbar extends LitElement {
@click=${this.openSeedModal}>
seed: <b>0x${seedHex}</b>
</span>
<button class="ghost" id="tour-btn" title="Replay the 10-step welcome tour"
aria-label="Replay welcome tour"
@click=${() => window.dispatchEvent(new CustomEvent('nv-show-tour'))}>
Tour
</button>
<button class="ghost" id="help-btn" title="Help (press ? any time)" aria-label="Open help"
@click=${() => window.dispatchEvent(new CustomEvent('nv-show-help'))}>
?