@molecule/app-tour
Core interface · tour · App (browser) · v1.0.2 · Apache-2.0
Tour core interface for molecule.dev.
npm install @molecule/app-tourHow it works
@molecule/app-tour is the tour core interface on the app (browser) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 1 provider: @molecule/app-tour-shepherd.
import { requireProvider, setProvider } from '@molecule/app-tour'
import { provider } from '@molecule/app-tour-shepherd'
setProvider(provider) // once, at startup (bonds.ts)
const tour = requireProvider().createTour({
steps: [
{
target: '[data-mol-id="editor"]',
title: 'Editor',
content: 'Write code here',
action: () => renderTourStep(tour.getCurrentStep()),
},
],
onComplete: () => markTourSeen(),
})
tour.start()Providers (1): @molecule/app-tour-shepherd
Works with: @molecule/app-bond
Reference
Tour core interface for molecule.dev.
Provides a standardized API for onboarding walkthrough and guided
tour UI components. Bond a provider (e.g. @molecule/app-tour-shepherd)
to supply the concrete implementation.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { requireProvider, setProvider } from '@molecule/app-tour'
import { provider } from '@molecule/app-tour-shepherd'
setProvider(provider) // once, at startup (bonds.ts)
const tour = requireProvider().createTour({
steps: [
{
target: '[data-mol-id="editor"]',
title: 'Editor',
content: 'Write code here',
action: () => renderTourStep(tour.getCurrentStep()),
},
],
onComplete: () => markTourSeen(),
})
tour.start()
Type
core
Installation
npm install @molecule/app-tour @molecule/app-bond
API
Interfaces
TourStep
A single step in a guided tour.
interface TourStep {
/** CSS selector for the target element to highlight. */
target: string
/** Title of the tour step. */
title: string
/** Content/description body for the step. */
content: string
/** Preferred placement of the tooltip relative to the target. */
placement?: 'top' | 'bottom' | 'left' | 'right'
/** Action to perform when the step is shown. */
action?: () => void
/** Async function that runs before the step is displayed. */
beforeShow?: () => Promise<void>
}
TourOptions
Configuration options for creating a tour.
interface TourOptions {
/** Steps to display in the tour. */
steps: TourStep[]
/** Callback when the tour is completed. */
onComplete?: () => void
/** Callback when the tour is cancelled. */
onCancel?: () => void
/** Whether to show a progress indicator. Defaults to `true`. */
showProgress?: boolean
/**
* Whether navigation buttons (back / next / done) should be rendered.
* Defaults to `true`. Surfaced back to the consumer's render code via
* `TourInstance.hasButtons`.
*/
showButtons?: boolean
/**
* Whether a backdrop overlay should be rendered. Defaults to `true`.
* Surfaced back to the consumer's render code via
* `TourInstance.hasOverlay`.
*/
overlay?: boolean
}
TourInstance
A live tour instance returned by the provider.
interface TourInstance {
/**
* Starts the tour from the beginning.
*/
start(): void
/**
* Advances to the next step.
*/
next(): void
/**
* Goes back to the previous step.
*/
previous(): void
/**
* Cancels the tour without completing it.
*/
cancel(): void
/**
* Marks the tour as complete and triggers the onComplete callback.
*/
complete(): void
/**
* Checks whether the tour is currently running.
*
* @returns `true` if the tour is active.
*/
isActive(): boolean
/**
* Returns the index of the current step.
*
* @returns Zero-based index of the current step.
*/
getCurrentStep(): number
/**
* Whether a backdrop overlay should be rendered for this tour.
*
* The provider tracks state only and draws nothing on screen — read this in
* your render code to decide whether to paint the backdrop. Reflects the
* resolved `overlay` value: the per-tour `TourOptions.overlay`, else
* the provider's default, else `true`.
*
* @returns `true` if the consumer should render a backdrop overlay.
*/
hasOverlay(): boolean
/**
* Whether navigation buttons (back / next / done) should be rendered.
*
* The provider draws no buttons itself — read this in your render code to
* decide whether to paint the nav controls. Reflects the resolved
* `showButtons` value: the per-tour `TourOptions.showButtons`, else the
* provider's default, else `true`.
*
* @returns `true` if the consumer should render navigation buttons.
*/
hasButtons(): boolean
}
TourProvider
Tour provider interface.
All tour providers must implement this interface to create and manage onboarding walkthrough / guided tour UI.
interface TourProvider {
/** Provider name identifier. */
readonly name: string
/**
* Creates a new tour instance.
*
* @param options - Configuration for the tour.
* @returns A tour instance for controlling the walkthrough.
*/
createTour(options: TourOptions): TourInstance
}
Functions
setProvider(provider)
Registers a tour provider as the active singleton.
function setProvider(provider: TourProvider): void
provider— The tour provider implementation to bond.
getProvider()
Retrieves the bonded tour provider, or null if none is bonded.
function getProvider(): TourProvider | null
Returns: The active tour provider, or null.
hasProvider()
Checks whether a tour provider has been bonded.
function hasProvider(): boolean
Returns: true if a tour provider is available.
requireProvider()
Retrieves the bonded tour provider, throwing if none is configured.
function requireProvider(): TourProvider
Returns: The active tour provider.
Available Providers
| Provider | Package |
|---|---|
| Shepherd.js | @molecule/app-tour-shepherd |
Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1
Runtime Dependencies
-
@molecule/app-bond -
The provider manages tour STATE — it does not draw the overlay. The bundled bond tracks the active step and fires each step's
actionplusonComplete/onCancel; the highlight/tooltip UI is the consumer's to render fromgetCurrentStep()and the step'starget/title/content. Don't expectstart()alone to put anything on screen. -
Read the
overlay/showButtonsintent back off the instance. Because the provider draws nothing,TourOptions.overlay/showButtonsare surfaced for the consumer viahasOverlay()/hasButtons()(resolved: per-tour option → provider default →true). Gate the backdrop and nav buttons your render code paints on those accessors rather than re-deriving the flags. -
The instance has NO change subscription — drive re-renders from the per-step
actioncallbacks (or wrapnext/previous), not by polling. -
targetis a CSS selector: prefer stable[data-mol-id="…"]selectors over styling class names (class strings are ClassMap-bond-owned and swappable). -
Step
title/contentare UI text — source them viat('key', values, { defaultValue }), and style the rendered tour UI withgetClassMap()from@molecule/app-ui. -
Wire it with THIS package's
setProvider()orbond('tour', …).setProvider()delegates into the shared@molecule/app-bondregistry, so both write the same slot;requireProviderthrows until one has run.
E2E Tests
Integration checklist — drive the real UI (live preview, no mocks), adapt
each item to this app's actual onboarding flow, and check every box off one
by one. A box you can't check is an integration bug to fix — not a skip. The
provider only tracks state, so every checkpoint is about the overlay the app
RENDERS from getCurrentStep() — verify what's on screen, not just the calls:
- Starting the tour renders step 1's tooltip (its
title/content) anchored to that step'stargetelement, with the target highlighted / spotlighted.start()alone paints nothing — the per-stepactionis what draws the overlay, so confirm the anchored tooltip actually appears. -
nextadvances in order: the tooltip + highlight move to each step'stargetand the progress indicator updates (e.g. "2 of 5" —getCurrentStep()is zero-based, so it reads step+1 ofsteps.length).previousmoves one step back.nexton the LAST step does not wrap or auto-finish (the bond no-ops past the end), so a visible Done/Finish control must callcomplete(). - Skip/close (
cancel()) ends the tour immediately — the overlay and tooltip disappear,isActive()is false — and firesonCancel. - Completing the last step fires
onCompleteand closes the tour (overlay and tooltip gone,isActive()false). - Seen-once: a returning user who completed OR dismissed the tour is not
shown it again after reload, while a fresh user is. The package has no
built-in "seen" state — the app must persist a flag in
onComplete/onCanceland gatestart()on it; verify the persistence survives a reload. - A step whose
targetselector matches no element is handled gracefully (the step is skipped or the tour ends) — it never crashes anchoring a tooltip to a null element (the bond keepstargetas a plain string and never touches the DOM, so this guard lives in the app's render code). - While the tour is active with
overlayon (i.e.hasOverlay()is true), the backdrop blocks interaction outside the current step — clicks reach only the tour controls and the highlighted target; ending the tour restores normal interaction. A tour created withoverlay: falsereportshasOverlay() === falseand your render code paints no backdrop. Likewise gate the nav buttons onhasButtons().