Files
homelable/frontend/src/walkthrough/steps.ts
T
Pouzor 8c56921375 feat(walkthrough): add Getting Started tour with first-run invite
Bespoke spotlight walkthrough (no new deps) that guides new users through the
main features. A version-stamped invite bubble offers the tour to new users and
re-offers it once to existing users after an upgrade; restartable from Settings.

- Multi-hole SVG-mask overlay keeps a ringed control and any open modal lit
- Steps: scan, scan history, inventory, nodes, edit, text/zone, grouping,
  style, imports, and a closing recap with a GitHub link
- Scan/history/inventory/import steps inject demo data (no backend calls) and
  are filtered out in standalone, which ends on a full-mode recap
- Persisted invite state via localStorage (utils/walkthrough.ts), live tour
  state via zustand (stores/walkthroughStore.ts)

ha-relevant: maybe
2026-07-19 00:40:08 +02:00

122 lines
4.5 KiB
TypeScript

/**
* Declarative Getting Started steps.
*
* `anchor` is a CSS selector for the element to ring/spotlight (undefined → the
* overlay lights any open modal, or centers the card). `action` is a key resolved
* against the walkthrough actions context on step enter (opens a modal, injects
* demo data, selects nodes, …). `mode: 'full'` marks a backend-only step that is
* filtered out of the standalone/public build. `link` renders a link in the card
* (used for the closing "questions?" step).
*/
export type StepPlacement = 'center' | 'top' | 'bottom' | 'left' | 'right' | 'auto'
export interface TourStep {
id: string
title: string
body: string
anchor?: string
placement?: StepPlacement
action?: string
mode?: 'full' | 'all'
link?: { label: string; href: string }
}
export const STEPS: TourStep[] = [
{
id: 'welcome',
title: 'Welcome to Homelable',
body: 'Take a quick tour of the main features — scanning your network, managing devices, and building your canvas. You can skip anytime and restart later from Settings.',
placement: 'center',
mode: 'all',
},
{
id: 'scan',
title: 'Scan your network',
body: 'Start here: run an IP scan to auto-discover devices on your network. Pick the ranges and ports, then launch — discovered devices land in your inventory for review.',
anchor: '[data-tour="scan-network"]',
placement: 'right',
action: 'openScanConfig',
mode: 'full',
},
{
id: 'scan-history',
title: 'Follow scan progress',
body: 'Scan History shows every run live. A running scan updates in place with elapsed time and device count — you can stop it here too. (This is example data.)',
placement: 'left',
action: 'openScanHistoryDemo',
mode: 'full',
},
{
id: 'inventory',
title: 'Review discovered devices',
body: 'Discovered devices wait in your inventory. For each one you can approve it onto the canvas, hide it, or delete it — with detected services and vendor shown. (Example devices.)',
placement: 'left',
action: 'openInventoryDemo',
mode: 'full',
},
{
id: 'nodes',
title: 'Your devices on the canvas',
body: 'Approved devices become nodes on the canvas. Each shows live status, IP, hostname and running services. Drag to arrange them and draw links between them.',
anchor: '.react-flow__node',
placement: 'auto',
mode: 'all',
},
{
id: 'node-edit',
title: 'Edit a device',
body: 'Double-click any node to edit it: name, type, IP, the status-check method, appearance, and its parent (e.g. a VM inside a Proxmox host). Changes are yours until you Save.',
placement: 'left',
action: 'editFirstNode',
mode: 'all',
},
{
id: 'text-zone',
title: 'Annotate with text & zones',
body: 'Add free Text labels and Zones (colored rectangles) to document your layout — group a rack, mark a VLAN, or leave a note. Both live under the canvas actions.',
anchor: '[data-tour="add-zone"]',
placement: 'right',
mode: 'all',
},
{
id: 'grouping',
title: 'Group related devices',
body: 'Select multiple nodes, then Create Group to box them together and drag them as one — perfect for a rack, a site, or a subnet.',
anchor: '[data-tour="create-group"]',
placement: 'left',
action: 'selectTwoNodes',
mode: 'all',
},
{
id: 'style',
title: 'Make it yours',
body: 'Switch the canvas theme from Style, or fine-tune colors, borders and fonts per node type. Your homelab, your look.',
anchor: '[data-tour="style"]',
placement: 'bottom',
action: 'openStyle',
mode: 'all',
},
{
id: 'imports',
title: 'Import from your stack',
body: 'Already running Zigbee2MQTT, Z-Wave JS, or Proxmox? Import devices directly from them instead of scanning — one click brings the whole topology in.',
anchor: '[data-tour="zigbee-import"]',
placement: 'right',
action: 'openZigbeeImport',
mode: 'full',
},
{
id: 'end',
title: "You're all set",
body: "That's the tour! Build your map, save it, and share a read-only view. In full mode you also get network scanning, a device inventory, and Zigbee / Z-Wave / Proxmox import. Have a question or an idea?",
placement: 'center',
mode: 'all',
link: { label: 'Ask on GitHub', href: 'https://github.com/Pouzor/homelable/issues' },
},
]
/** Steps for the current build — backend-only steps are dropped in standalone. */
export function getSteps(standalone: boolean): TourStep[] {
return STEPS.filter((s) => s.mode !== 'full' || !standalone)
}