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? }.targetis the logical key carried bydata-guide.advanceOnis'click'orundefined; a step declaring it advances when the user clicks the target, and impliesinteractive(seeActiveStepbelow). See Tours.Tour:{ id: string; steps: Step[] }.TourStatus:'idle' | 'running' | 'paused' | 'completed'.TourProgress:{ status: 'in-progress' | 'completed'; stepIndex: number }. The value persisted undertour:<id>.
Core: checklist types
ChecklistItem:{ id, title?, titleKey?, body?, bodyKey?, tourId?, href? }. An item with atourIdcompletes when that tour finishes; an item with anhrefnavigates and completes nothing.Checklist:{ id: string; items: ChecklistItem[] }.ChecklistProgress:{ completed: string[]; dismissed: boolean }. The value persisted underchecklist:<id>.ResolvedChecklistItem:{ id, title, body, completed, tourId?, href? }. An item after text resolution and progress lookup, as returned byuseChecklist.
Core: hotspot types
See Hotspots for the feature itself; this is the type reference.
Hotspot:{ id, target, title?, titleKey?, body?, bodyKey?, tourId?, placement? }.targetis the logical key carried bydata-guide, the same as a step’s.tourIdnames a tour started from the hotspot’s bubble.ResolvedHotspot:{ id, target, title, body, seen, tourId?, placement? }. A hotspot after text resolution andseenlookup, as returned byuseHotspots.HotspotsProgress:{ seen: string[] }. The value persisted under the single keyhotspots:seen.isHotspotsProgress(value: unknown): value is HotspotsProgress: guard requiring aseenarray 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: aMapfor the lifetime of the page. The choice for tests.createBrowserStorage(namespace = 'guide'): GuideStorage: JSON inlocalStorageunder<namespace>:<key>. Returnsnullrather than throwing when storage is unavailable.isTourProgress(value: unknown): value is TourProgress: guard used at the read site. Requires an integerstepIndexof zero or more and a knownstatus.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: returnsvalueif set, otherwise the translatedkey, 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.interactiveandawaitsActionare derived, not read offstepdirectly:interactiveis true when the step setsinteractive: trueor declaresadvanceOn;awaitsActionis true only when the step declaresadvanceOn. Renderers read these, notstep.interactive, which is leftundefinedon a step that only setsadvanceOn. See Tours.ChecklistProvider(props: ChecklistProviderProps): holds checklist progress, ticks items when their tour completes, and persists. Nest it insideGuideProviderfortourIditems 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).restoredis 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 insideGuideProviderfor a hotspot’stourIdto 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 aGuideProvider.UseTourResult:{ start(options?: { from?: number; resume?: boolean }): Promise<void>; next; previous; stop; status: TourStatus; stepIndex: number }.statusandstepIndexread'idle'and0when another tour is the current one. There is nocomplete(): a tour completes whennext()is called on its last step.useGuideStep(): ActiveStep | null: the current step, ornullwhen 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 aChecklistProvider, and throws on an unknown checklist id.UseChecklistResult:{ items: ResolvedChecklistItem[]; completedCount; total; isComplete; dismissed; restored; activate(itemId); toggle(itemId); complete(itemId); dismiss(); reset() }.restoredis whether this checklist’s own initial storage read has settled:trueimmediately with nostorageprop,trueonce 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 aHotspotProvider.UseHotspotsResult:{ hotspots: ResolvedHotspot[]; restored: boolean; open(hotspotId): void; startTour(hotspotId): void; reset(): void; notifyShown(hotspotId): void }.hotspotslists every hotspot, seen ones included, each carrying its ownseen.restoredis whether the initial storage read has settled, the same shape asuseChecklist’s.openmarks a hotspot seen and emitshotspot:open.startTourstarts the tour named by the hotspot’stourId, if it has one.notifyShownis for renderers: call it once a marker is actually drawn, sohotspot:showfires 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.STARTcarriestourIdandstepIndex;NEXTcarriesstepCount.initialTourState: TourState:{ tourId: null, stepIndex: 0, status: 'idle' }.tourReducer(state: TourState, action: TourAction): TourState: pure reducer.NEXTon the last step moves tocompleted;NEXTandPREVIOUSfrompausedresume.
Core: routing
matchRoute(pattern: string, pathname: string): boolean: segment match supporting:paramand 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 aMutationObserver, 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 andResizeObservernotifications.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'requirestabIndex={-1}on the container.useAnnouncer(): (message: string) => void: writes into a single shared, visually hiddenaria-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,nullbefore 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 theawaitingActionlabel andArrowRightis 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 toNext,Back,Finish,Close,Click the highlighted element to continue..closeis the close button’s accessible name;awaitingActionis 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 atourId, a button that starts that tour. Rendersnulluntilrestoredis 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 }, defaultingstartTourtoShow meandclosetoClose.markeris 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. Rendersnulluntilrestoredis true, and once dismissed.ChecklistProps:{ checklistId, title?, onDismiss?, onActivate?, labels? }.onActivatereceives theResolvedChecklistItem.ChecklistLabels:{ dismiss: string; progress: (completedCount: number, total: number) => string; markComplete: (itemTitle: string) => string; markNotComplete: (itemTitle: string) => string }, defaulting toDismiss,<n> of <total>,Mark <item title> as completeandMark <item title> as not complete.labelstakes aPartial, so anything left out keeps its default.ChecklistLauncher(props: ChecklistLauncherProps): a corner button showingdone/totalwith 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: extendsChecklistLabelswithfabLabel: (title: string, completedCount: number, total: number) => stringanddismissed: (title: string) => string, defaulting to<title>, <n> of <total> completeand<title> dismissed. The launcher passes its resolved labels down to theChecklistit renders in its popover, so one object covers both.
Related
- Getting started for installation and the first tour.
- Hotspots for the feature these types and hooks belong to.
- Persistence for
GuideStoragein depth. - Accessibility for what the a11y primitives guarantee.