APOLLO VISION LABS

API reference

Every exported symbol of guide-core and guide-mui, with its signature and what it does.

Two packages. @apollovisionlabs/guide-core exports 57 symbols and renders nothing. @apollovisionlabs/guide-mui exports 16 and renders the core on MUI 7 or MUI 9. React 19 is the peer for both.

One name collision

Checklist is a type in the core and a component in the MUI package. Importing both into the same module needs an alias:

import { useChecklist, type Checklist as ChecklistData } from '@apollovisionlabs/guide-core'
import { Checklist } from '@apollovisionlabs/guide-mui'

const onboarding: ChecklistData = { id: 'onboarding', items: [] }

Aliasing the type rather than the component is the smaller change, since the component appears in JSX and the type does not.

Core: tour and step types

  • Rect: { top: number; left: number; width: number; height: number }. Viewport coordinates of a measured element.
  • Placement: 'top' | 'bottom' | 'left' | 'right'. Where the popover sits relative to its target.
  • MissingTargetPolicy: 'skip' | 'wait' | 'error'. What to do when a target never appears.
  • Step: { target, route?, navigateTo?, placement?, interactive?, advanceOn?, title?, titleKey?, body?, bodyKey?, onMissingTarget? }. target is the logical key carried by data-guide. advanceOn is 'click' or undefined; a step declaring it advances when the user clicks the target, and implies interactive (see ActiveStep below). See Tours.
  • Tour: { id: string; steps: Step[] }.
  • TourStatus: 'idle' | 'running' | 'paused' | 'completed'.
  • TourProgress: { status: 'in-progress' | 'completed'; stepIndex: number }. The value persisted under tour:<id>.

Core: checklist types

  • ChecklistItem: { id, title?, titleKey?, body?, bodyKey?, tourId?, href? }. An item with a tourId completes when that tour finishes; an item with an href navigates and completes nothing.
  • Checklist: { id: string; items: ChecklistItem[] }.
  • ChecklistProgress: { completed: string[]; dismissed: boolean }. The value persisted under checklist:<id>.
  • ResolvedChecklistItem: { id, title, body, completed, tourId?, href? }. An item after text resolution and progress lookup, as returned by useChecklist.

Core: hotspot types

See Hotspots for the feature itself; this is the type reference.

  • Hotspot: { id, target, title?, titleKey?, body?, bodyKey?, tourId?, placement? }. target is the logical key carried by data-guide, the same as a step’s. tourId names a tour started from the hotspot’s bubble.
  • ResolvedHotspot: { id, target, title, body, seen, tourId?, placement? }. A hotspot after text resolution and seen lookup, as returned by useHotspots.
  • HotspotsProgress: { seen: string[] }. The value persisted under the single key hotspots:seen.
  • isHotspotsProgress(value: unknown): value is HotspotsProgress: guard requiring a seen array of strings.

Core: storage and text

  • GuideStorage: { read<T>(key: string): Promise<T | null>; write<T>(key: string, value: T): Promise<void> }. Generic over the stored value; the key is namespaced by the caller.
  • createMemoryStorage(initial?: Record<string, unknown>): GuideStorage: a Map for the lifetime of the page. The choice for tests.
  • createBrowserStorage(namespace = 'guide'): GuideStorage: JSON in localStorage under <namespace>:<key>. Returns null rather than throwing when storage is unavailable.
  • isTourProgress(value: unknown): value is TourProgress: guard used at the read site. Requires an integer stepIndex of zero or more and a known status.
  • isChecklistProgress(value: unknown): value is ChecklistProgress: guard requiring a string array and a boolean.
  • Translate: (key: string) => string. The provider’s translation hook.
  • resolveText(value: string | undefined, key: string | undefined, translate: Translate | undefined): string: returns value if set, otherwise the translated key, otherwise the raw key, otherwise an empty string.

Core: the GuideEvent union

GuideEvent is the discriminated union passed to onEvent. Tour variants are emitted by GuideProvider, checklist variants by ChecklistProvider, hotspot variants by HotspotProvider.

Variant Payload Fires when
tour:start tourId, stepIndex start() succeeds, with the index it actually starts on, resume included
tour:complete tourId next() is called on the last step
tour:stop tourId, stepIndex stop() is called
step:show tourId, stepIndex, target The tour is running and the step’s target element has been resolved
target:missing tourId, stepIndex, target The wait for a target expires, before the policy is applied
checklist:item-complete checklistId, itemId An item goes from not completed to completed
checklist:complete checklistId The last remaining item completes
checklist:dismiss checklistId dismiss() is called
hotspot:show hotspotId A hotspot’s marker is actually drawn on screen. Fires once per hotspot per mount.
hotspot:open hotspotId The hotspot’s bubble is opened, which also marks it seen. Does not repeat for a bubble already open.

Two silences worth knowing. Unticking an item emits nothing, and neither checklist:item-complete nor checklist:complete repeats for an item already ticked. And the error missing target policy stops the tour without a tour:stop: only an explicit stop() emits it, so target:missing is the event to watch for that case.

Core: providers

  • GuideProvider(props: GuideProviderProps): holds tour state, resolves targets, delegates navigation and persists progress. Throws on duplicate tour ids.
  • GuideProviderProps: { tours, children, navigate?, location?, storage?, translate?, onEvent?, onMissingTarget = 'wait', targetTimeoutMs = 5000 }.
  • GuideContext: React.Context<GuideContextValue | null>. Exported for a custom renderer.
  • GuideContextValue: { state, activeStep, start, next, previous, stop }.
  • ActiveStep: { tourId, step, stepIndex, stepCount, element, rect, interactive, awaitsAction, title, body, isFirst, isLast, next, previous, stop }. Everything a renderer needs for the current step. interactive and awaitsAction are derived, not read off step directly: interactive is true when the step sets interactive: true or declares advanceOn; awaitsAction is true only when the step declares advanceOn. Renderers read these, not step.interactive, which is left undefined on a step that only sets advanceOn. See Tours.
  • ChecklistProvider(props: ChecklistProviderProps): holds checklist progress, ticks items when their tour completes, and persists. Nest it inside GuideProvider for tourId items to work.
  • ChecklistProviderProps: { checklists, children, storage?, translate?, navigate?, onEvent? }.
  • ChecklistContext: React.Context<ChecklistContextValue | null>.
  • ChecklistContextValue: { checklists, progress, translate?, restored, activate, toggle, complete, dismiss, reset }. The context methods take (checklistId, itemId). restored is keyed by checklist id, one entry per checklist.
  • HotspotProvider(props: HotspotProviderProps): holds which hotspots have been opened, starts a hotspot’s tour, and persists. Nest it inside GuideProvider for a hotspot’s tourId to work. Throws on duplicate hotspot ids. See Hotspots.
  • HotspotProviderProps: { hotspots, children, storage?, translate?, onEvent? }.
  • HotspotContext: React.Context<HotspotContextValue | null>.
  • HotspotContextValue: { hotspots, seen, translate?, restored, open, startTour, reset, notifyShown }.

Core: hooks

  • useTour(tourId: string): UseTourResult: controls one tour. Throws outside a GuideProvider.
  • UseTourResult: { start(options?: { from?: number; resume?: boolean }): Promise<void>; next; previous; stop; status: TourStatus; stepIndex: number }. status and stepIndex read 'idle' and 0 when another tour is the current one. There is no complete(): a tour completes when next() is called on its last step.
  • useGuideStep(): ActiveStep | null: the current step, or null when no tour is active. The hook a custom renderer builds on.
  • useChecklist(checklistId: string): UseChecklistResult: resolved items and the actions for one checklist. Throws outside a ChecklistProvider, and throws on an unknown checklist id.
  • UseChecklistResult: { items: ResolvedChecklistItem[]; completedCount; total; isComplete; dismissed; restored; activate(itemId); toggle(itemId); complete(itemId); dismiss(); reset() }. restored is whether this checklist’s own initial storage read has settled: true immediately with no storage prop, true once this checklist’s own read has resolved or rejected. Settles independently per checklist. See Checklist.
  • useHotspots(): UseHotspotsResult: every hotspot and the actions on the whole set. Throws outside a HotspotProvider.
  • UseHotspotsResult: { hotspots: ResolvedHotspot[]; restored: boolean; open(hotspotId): void; startTour(hotspotId): void; reset(): void; notifyShown(hotspotId): void }. hotspots lists every hotspot, seen ones included, each carrying its own seen. restored is whether the initial storage read has settled, the same shape as useChecklist’s. open marks a hotspot seen and emits hotspot:open. startTour starts the tour named by the hotspot’s tourId, if it has one. notifyShown is for renderers: call it once a marker is actually drawn, so hotspot:show fires once per hotspot per mount. See Hotspots.

Core: state machine

  • TourState: { tourId: string | null; stepIndex: number; status: TourStatus }.
  • TourAction: START | NEXT | PREVIOUS | PAUSE | RESUME | STOP. START carries tourId and stepIndex; NEXT carries stepCount.
  • initialTourState: TourState: { tourId: null, stepIndex: 0, status: 'idle' }.
  • tourReducer(state: TourState, action: TourAction): TourState: pure reducer. NEXT on the last step moves to completed; NEXT and PREVIOUS from paused resume.

Core: routing

  • matchRoute(pattern: string, pathname: string): boolean: segment match supporting :param and a * wildcard that accepts everything from that segment on. Query strings and trailing slashes are ignored.
  • isLiteralRoute(pattern: string): boolean: true when the pattern has neither : nor *, which is when it can be used as a navigation destination.

Core: DOM helpers

  • useTargetElement(target: string | null, options?: UseTargetElementOptions): { element: HTMLElement | null; timedOut: boolean }: resolves [data-guide="<target>"], waits with a MutationObserver, and reports a timeout without giving up on a later appearance.
  • UseTargetElementOptions: { timeoutMs = 5000; attribute = 'data-guide' }.
  • useElementRect(element: HTMLElement | null): Rect | null: measures before paint and re-measures on scroll, resize and ResizeObserver notifications.
  • findMissingTargets(tour: Tour, location: string | undefined, attribute = 'data-guide'): string[]: the targets of the steps valid on this route that are not in the DOM. Used by the provider’s development warning; usable in your own tests.

Core: accessibility primitives

  • useFocusTrap(container: HTMLElement | null, active: boolean, options?: UseFocusTrapOptions): void: cycles Tab inside the container and restores the previously focused element on teardown.
  • UseFocusTrapOptions: { initialFocus?: 'first' | 'container' }. 'container' requires tabIndex={-1} on the container.
  • useAnnouncer(): (message: string) => void: writes into a single shared, visually hidden aria-live="polite" node.
  • usePrefersReducedMotion(): boolean: tracks (prefers-reduced-motion: reduce), including changes made mid session.

MUI package

  • GuideTour(props?: GuideTourProps): the one component a tour needs. Renders the spotlight and the popover for the active step, null before mount, and an Escape handler alone while a target is awaited.
  • GuideTourProps: { zIndex?, padding?, radius?, labels? }.
  • StepPopover(props: StepPopoverProps): the step dialog: title, body, position counter, Back and Next, close button, arrow and Escape keys. When the step awaits an action, Next is replaced by the awaitingAction label and ArrowRight is ignored.
  • StepPopoverProps: { anchorEl, open, title, body, stepIndex, stepCount, isFirst, isLast, placement = 'bottom', zIndex?, describeElement?, modal = true, awaitsAction = false, labels?, onNext, onPrevious, onStop }.
  • StepPopoverLabels: { next; previous; finish; close; awaitingAction }, defaulting to Next, Back, Finish, Close, Click the highlighted element to continue.. close is the close button’s accessible name; awaitingAction is shown in place of the primary button while the step waits for the user to act.
  • Spotlight(props: SpotlightProps): the dimming overlay with a hole cut over the target. Clicking outside the hole stops the tour; clicking inside it does nothing unless the step is interactive.
  • SpotlightProps: { rect, padding = 8, radius = 8, interactive = false, zIndex?, onDismiss? }.
  • Hotspots(props?: HotspotsProps): renders a marker at each unseen hotspot’s target; clicking one opens a bubble with the hotspot’s title, body, and, when it names a tourId, a button that starts that tour. Renders null until restored is true, and while a tour is running or paused. See Hotspots.
  • HotspotsProps: { labels?, placement = 'bottom', zIndex? }.
  • HotspotLabels: { marker: (title: string) => string; startTour: string; close: string }, defaulting startTour to Show me and close to Close. marker is a function, not a fixed string, because word order around a name varies by language; its default is (title) => `Show what is new: ${title}`.
  • Checklist(props: ChecklistProps): the list itself: progress bar, one row per item, a dismiss button. Renders null until restored is true, and once dismissed.
  • ChecklistProps: { checklistId, title?, onDismiss?, onActivate?, labels? }. onActivate receives the ResolvedChecklistItem.
  • ChecklistLabels: { dismiss: string; progress: (completedCount: number, total: number) => string; markComplete: (itemTitle: string) => string; markNotComplete: (itemTitle: string) => string }, defaulting to Dismiss, <n> of <total>, Mark <item title> as complete and Mark <item title> as not complete. labels takes a Partial, so anything left out keeps its default.
  • ChecklistLauncher(props: ChecklistLauncherProps): a corner button showing done/total with a progress ring, opening the checklist in a modal popover.
  • ChecklistLauncherProps: { checklistId, title?, placement = 'bottom-right', labels? }, placement being one of the four corners.
  • ChecklistLauncherLabels: extends ChecklistLabels with fabLabel: (title: string, completedCount: number, total: number) => string and dismissed: (title: string) => string, defaulting to <title>, <n> of <total> complete and <title> dismissed. The launcher passes its resolved labels down to the Checklist it renders in its popover, so one object covers both.