Installation
import { WrTour } from 'ngwr/tour';
// Nothing to import into a component — the service owns the overlay.
private readonly tour = inject(WrTour);Run a tour
Steps are data, not markup: start() takes an array and the service owns the overlay, the cut-out, focus and the keyboard. Escape ends the tour and focus returns where it began. The demo below has a deliberate fourth step pointing at an element that is not on the page — it is skipped rather than shown floating, which is what keeps a tour alive when a feature sits behind a flag or a permission.
this.tour.start([
{ target: '[data-tour="search"]', title: 'Start here', content: 'Type a name…' },
{ target: '[data-tour="filter"]', content: 'Filters stack.', placement: 'right' },
{ target: '[data-tour="save"]', content: 'Nothing is saved until you press this.', placement: 'top' },
]);Reading the state
Progress is exposed as signals, so a template can show its own progress bar or a “resume tour” affordance without subscribing to anything.
// Signals, so a template can react without a subscription.
tour.active(); // is a tour running
tour.index(); // 0-based step, -1 when idle
tour.total(); // how many steps
tour.step(); // the current WrTourStep | nullAPI
| Name | Description | Type | Default |
|---|---|---|---|
WrTour | Injectable service. No module, no component to place. | service | — |
start(steps) | Begin a tour. Restarts if one is running; a no-op under SSR. | (steps: readonly WrTourStep[]) => void | — |
next() | Advance. Past the last step it finishes the tour. | () => void | — |
prev() | Go back. Stays put on the first step. | () => void | — |
stop() | End the tour and return focus where it started. | () => void | — |
active | Whether a tour is running. | Signal<boolean> | false |
index | 0-based index of the current step, -1 when idle. | Signal<number> | -1 |
total | Step count of the running tour. | Signal<number> | 0 |
step | The step being shown. | Signal<WrTourStep | null> | null |
WrTourStep | One stop on the tour. | interface | — |
target | CSS selector resolved when the step opens, or the element itself. A step matching nothing is SKIPPED. | string | HTMLElement | — (required) |
title | Heading above the copy. | string | — |
content | The step's body text. | string | — (required) |
placement | Preferred side. Falls back to the opposite side near a viewport edge. | 'top' | 'bottom' | 'left' | 'right' | 'bottom' |