@flowsterix/react
v1.9.0
Published
React bindings for Flowsterix - guided tours and onboarding flows
Maintainers
Readme
@flowsterix/react Maintainer Documentation
This is the maintainer-facing source of truth for @flowsterix/react.
It covers:
- package concepts and architecture
- runtime data flows and state transitions
- capability coverage map
- exhaustive API inventory (main entry and subpath exports)
- test and release maintenance workflow
It is intentionally implementation-oriented and not end-user onboarding docs.
Quick Facts
- package root:
packages/react - primary source entry:
src/index.tsx - published outputs:
dist/* - package exports:
@flowsterix/react@flowsterix/react/router@flowsterix/react/router/tanstack@flowsterix/react/router/react-router@flowsterix/react/router/next-app@flowsterix/react/router/next-pages@flowsterix/react/devtools
Concepts and Core Model
@flowsterix/react is a React runtime around core flow state (@flowsterix/core) plus UI primitives and integration helpers.
Core concepts:
- Flow runtime:
- Active flow and active step are sourced from the core store and exposed by
TourProvider.
- Active flow and active step are sourced from the core store and exposed by
- Target resolution:
- Step targets are resolved to element + rect snapshots (
useTourTarget) withrectSourceprovenance.
- Step targets are resolved to element + rect snapshots (
- HUD composition:
useHudStateanduseTourHudderive renderability, fallback strategy, lock behavior, and UX metadata.
- Overlay and popover:
useTourOverlaycomputes cutout geometry.OverlayBackdropandTourPopoverPortalrender visual primitives and transition behavior.
- Cross-step handoff:
- Overlay and popover preserve cached position during resolving windows and promote to live rect on gating conditions.
- Motion strategy:
- Motion can run as spring/tween/reduced via adapter abstraction.
- Router gating:
- Route signals can pause/resume or advance flows through route-aware hooks and adapters.
Architecture Map
flowchart TD
A["TourProvider<br/>(src/context.tsx)"] --> B["useTourTarget<br/>(resolve rect, scroll, source)"]
A --> C["useHudState<br/>(step render state, fallback)"]
B --> C
B --> I["useStepTransitionPhase<br/>(scroll settle coordinator)"]
I --> C
C --> D["useTourHud<br/>(HUD behavior + lock)"]
I -->|phase| E["useTourOverlay<br/>(overlay geometry)"]
I -->|phase| F["TourPopoverPortal<br/>(position)"]
D --> F
E --> G["OverlayBackdrop"]
D --> H["TourFocusManager"]Runtime Data Flows
1. Step to Target to HUD
TourProviderexposesactiveFlowId,activeStep,state.useTourTargetresolves target:
- selector/getNode/screen resolution
- viewport/observer/raf updates
rectSourceassignment (none|live|stored|viewport)- step-enter scroll and auto-scroll safeguards
useHudStatecombines flow state and target state:
- route mismatch handling
- hidden/missing fallback via
useHiddenTargetFallback - grace-period behavior and render gating
useTourHudderives:
- overlay config
- popover config
- body scroll lock + constrained mode
2. Step Transition Coordinator
Problem:
- During cross-step smooth scroll, live rect can be in transient positions.
- Immediate promotion causes visual jumps or settle artifacts.
- Previously, overlay and popover each ran independent motion tracking (duplicated ~70 lines), settling at different times.
Solution — useStepTransitionPhase coordinator:
- Single source of truth for the transition lifecycle:
idle → scrolling → settling → ready. - Both
useTourOverlayandTourPopoverPortalreadphasefrom the coordinator instead of tracking motion independently. - Rect promotion is gated behind
phase === 'ready'.
Step transition visual model — fade-out → work → fade-in:
next() → fade out highlight + popover → scroll + settle → phase="ready" → fade in at new position- On step change the highlight cutout is suppressed (no SVG rendered) and the popover fades to opacity 0.
- The backdrop overlay stays visible throughout — only the cutout and popover disappear.
- Suppression is held for at least the
stepTransitionFadeOutduration (default 180 ms) so the fade-out completes even when the coordinator settles quickly (element already in viewport). - Within-step rect changes (e.g. target resize) still use the spring/tween
overlayHighlighttransition — no fade for same-step updates.
Phase model:
idle ──► scrolling ──► settling ──► ready
│
(step change resets) ◄──────┘Settlement detection:
- Primary:
scrollendevent (Chrome 114+, Firefox 109+, Safari 17.4+) as fast-path. - Fallback: 6 consecutive RAF frames where rect delta < 0.5px (deterministic per frame delivery, not wall-clock).
- Visibility gate: after rect settles and is in viewport, the element must be ≥85% visible (not clipped by ancestor
overflow). Handles targets inside expanding sidebars, accordions, or collapsible panels without requiringwaitFor. Safety timeout: 3 s — after which the coordinator accepts the current position. - Both paths converge on
settling → ready.
Scroll retry:
- Max 2 total scroll-into-view attempts (down from 10 polling iterations).
- After settling, if target is not in viewport, one retry scroll is dispatched.
Implementation:
src/hooks/useStepTransitionPhase.ts— coordinator hooksrc/hooks/settleUtils.ts— shared constants and pure functions (extracted from overlay + popover)- Overlay and popover consume
phasevia options/props; no internal motion tracking. AnimationAdapterTransitionsexposesstepTransitionFadeOut(default 180 ms) andstepTransitionFadeIn(default 220 ms) for controlling the fade timing. ThereducedMotionAnimationAdaptersets both to 0.001 s.
3. Scroll and Lock Behavior
- Normal lock path:
useBodyScrollLock - Oversized target path:
useConstrainedScrollLock - Margin semantics:
scrollMargin.ts - Target initial scroll on step entry:
useTourTarget.ts(ensureElementInViewin useLayoutEffect) - Scroll retry and settle coordination:
useStepTransitionPhase.ts
Capability Coverage Matrix
| Capability | Primary APIs | Implementation |
| --- | --- | --- |
| Flow runtime provider | TourProvider, useTour, useTourEvents | src/context.tsx |
| Labels/i18n surface | defaultLabels, useTourLabels | src/labels.ts |
| Target acquisition and rect provenance | useTourTarget | src/hooks/useTourTarget.ts |
| HUD state derivation | useHudState, useTourHud | src/hooks/useHudState.ts, src/hooks/useTourHud.ts |
| Hidden/missing fallback handling | useHiddenTargetFallback | src/hooks/useHiddenTargetFallback.ts |
| Step transition coordination | useStepTransitionPhase | src/hooks/useStepTransitionPhase.ts, src/hooks/settleUtils.ts |
| Unified overlay geometry and state | useTourOverlay, OverlayBackdrop | src/hooks/useTourOverlay.ts, src/components/OverlayBackdrop.tsx |
| Popover positioning modes and persistence | TourPopoverPortal | src/components/TourPopoverPortal.tsx |
| Focus dominance and trap management | useTourFocusDominance, TourFocusManager | src/hooks/useTourFocusDominance.ts, src/components/TourFocusManager.tsx |
| Tour controls state | useTourControls | src/hooks/useTourControls.ts |
| Delay progress | useDelayAdvance | src/hooks/useDelayAdvance.ts |
| Motion abstraction and strategy | adapter exports + useHudMotion | src/motion/* |
| Body lock and constrained lock | useBodyScrollLock, useConstrainedScrollLock | src/hooks/useBodyScrollLock.ts, src/hooks/useConstrainedScrollLock.ts |
| Route channel and matching | getCurrentRoutePath, notifyRouteChange, subscribeToRouteChanges, createPathString, matchRoute | src/router/routeGating.ts, src/router/utils.ts |
| Framework router adapters | router subpath hooks/components | src/router/*Adapter.tsx, src/router/tanstackRouterSync.tsx |
| Radix dialog integration | useRadixDialogAdapter, useRadixTourDialog, registry exports | src/adapters/radixDialog.ts, src/hooks/useRadixTourDialog.ts, src/dialog/DialogRegistryContext.tsx |
| DevTools surface | @flowsterix/react/devtools exports | src/devtools/* |
API Inventory (Exhaustive)
This section is intended to cover every exported identifier in source.
Main Entry: @flowsterix/react
Runtime exports
- Core runtime:
TourProvideruseTouruseTourEvents
- Labels:
defaultLabelsuseTourLabels
- Target and HUD hooks:
useTourTargetuseHudStateuseHudDescriptionuseHudShortcutsuseTourHuduseTourOverlayuseHudTargetIssue
- Dialog and registry:
useRadixDialogAdapterwaitForDomuseRadixTourDialogDialogRegistryProvideruseDialogRegistryuseDialogRegistryOptional
- Focus and controls:
useTourFocusDominanceuseTourControlsuseDelayAdvance
- Components:
OverlayBackdropTourPopoverPortalTourFocusManager
- Motion:
AnimationAdapterProviderdefaultAnimationAdapterreducedMotionAnimationAdaptertweenAnimationAdapteruseAnimationAdapterusePreferredAnimationAdapteruseHudMotion
- Step transition:
useStepTransitionPhase
- Low-level hooks/utilities:
useAdvanceRulesuseBodyScrollLockuseConstrainedScrollLockuseHiddenTargetFallbackuseViewportRectcreateWaitForPredicateController
- Router utility exports (main entry safe subset):
getCurrentRoutePathnotifyRouteChangesubscribeToRouteChangescreatePathString
Type exports
- Context/provider:
DelayAdvanceInfoTourContextValueTourProviderProps
- Labels:
TourLabels
- Target:
TourTargetInfo
- Step transition:
StepTransitionPhaseUseStepTransitionPhaseOptionsUseStepTransitionPhaseResult
- HUD state and hooks:
UseHudStateOptionsUseHudStateResultUseHudDescriptionOptionsUseHudDescriptionResultUseHudShortcutsOptionsTourHudDescriptionTourHudFocusManagerStateTourHudOverlayConfigTourHudPopoverConfigUseTourHudOptionsUseTourHudResultHudTargetIssueUseHudTargetIssueOptionsUseHudTargetIssueResult
- Overlay and popover:
TourOverlayRectTourOverlaySegmentUseTourOverlayOptionsUseTourOverlayResultOverlayBackdropPropsOverlayBackdropTransitionsOverrideTourPopoverLayoutModeTourPopoverPortalPropsTourPopoverPortalRenderPropsTourFocusManagerProps
- Dialog:
RadixDialogAdapterResultUseRadixDialogAdapterOptionsUseRadixTourDialogParamsUseRadixTourDialogResultDialogControllerDialogRegistryContextValue
- Focus, controls, delay:
UseTourFocusDominanceOptionsUseTourFocusDominanceResultTourControlsStateDelayAdvanceProgress
- Motion:
AnimationAdapterAnimationAdapterComponentsAnimationAdapterProviderPropsAnimationAdapterTransitionsUseAnimationAdapterOptionsUseHudMotionResult
- Scroll/fallback/predicate:
ConstrainedScrollLockOptionsUseHiddenTargetFallbackConfigUseHiddenTargetFallbackResultWaitForPredicateControllerWaitForPredicateControllerOptions
Subpath: @flowsterix/react/router
Runtime exports:
getCurrentRoutePathmatchRoutenotifyRouteChangerouteGatingChannelsubscribeToRouteChangescreatePathString
Subpath: @flowsterix/react/router/tanstack
Runtime exports:
useTanStackRouterTourAdaptergetTanStackRoutergetTourRoutersetTanStackRoutersetTourRouterTanStackRouterSync
Type exports:
TanStackRouterSyncProps
Subpath: @flowsterix/react/router/react-router
Runtime exports:
useReactRouterTourAdapter
Subpath: @flowsterix/react/router/next-app
Runtime exports:
useNextAppRouterTourAdapter
Subpath: @flowsterix/react/router/next-pages
Runtime exports:
useNextPagesRouterTourAdapter
Subpath: @flowsterix/react/devtools
Runtime exports:
- Provider/context:
DevToolsProviderDevToolsContextuseDevToolsContextuseDevToolsContextRequired
- Components:
GrabberOverlayStepListSortableStepItemStepItemStepItemDragPreviewToolbarTabNavFlowsTabFlowItemFlowEditModal
- Hooks:
useGrabModeuseStepStoreuseElementInfouseFlowsData
- Utilities:
generateSelectorextractSourceextractComponentHierarchyformatSourcePathgetVSCodeLinkloadStepssaveStepsclearSteps
Type exports:
- Provider/context:
DevToolsProviderPropsDevToolsContextValueFlowStorageEntry
- Components:
GrabberOverlayPropsStepListPropsStepItemPropsStepItemDragPreviewPropsToolbarPropsTabNavPropsFlowsTabPropsFlowItemPropsFlowEditModalProps
- Hooks/data:
UseGrabModeResultUseStepStoreResultFlowDataUseFlowsDataResult
- Types:
DevToolsExportDevToolsStateDevToolsTabElementInfoElementSourceGrabbedStepGrabMode
DevTools export payload contract (DevToolsExport):
version:'1.1'steps[*].name: user-editable step namesteps[*].url: captured page URL at selection timesteps[*].selector: generated selector used for target capture
Files and Responsibility Map
- Provider and runtime contract:
src/context.tsxsrc/index.tsx
- Labels:
src/labels.ts
- HUD and render primitives:
src/hooks/useHudState.tssrc/hooks/useTourHud.tssrc/hooks/useTourOverlay.tssrc/components/OverlayBackdrop.tsxsrc/components/TourPopoverPortal.tsxsrc/components/TourFocusManager.tsx
- Step transition coordination:
src/hooks/useStepTransitionPhase.tssrc/hooks/settleUtils.ts
- Target and scroll mechanics:
src/hooks/useTourTarget.tssrc/hooks/useBodyScrollLock.tssrc/hooks/useConstrainedScrollLock.tssrc/hooks/scrollMargin.ts
- Dialog integration:
src/adapters/radixDialog.tssrc/hooks/useRadixTourDialog.tssrc/dialog/DialogRegistryContext.tsx
- Motion:
src/motion/animationAdapter.tsxsrc/motion/useHudMotion.ts
- Router:
src/router/routeGating.tssrc/router/*Adapter.tsxsrc/router/tanstackRouterSync.tsx
- DevTools:
src/devtools/*
Local Workflow
Run from repo root:
pnpm --filter @flowsterix/react test
pnpm --filter @flowsterix/react typecheck
pnpm --filter @flowsterix/react buildImportant constraints:
- package exports point to
dist - package publishes only
dist - runtime verification in consuming apps may require rebuilding this package
Debugging Checklist
- Confirm runtime state:
activeFlowId- active step id
- flow status
- Confirm target state:
statusvisibilityrectSourcelastResolvedRect
- Confirm step transition phase:
transitionPhase.phase(idle|scrolling|settling|ready)transitionPhase.settledRect(set onready)- cached anchor existence in overlay/popover
- Confirm motion mode:
- spring/tween setting
- reduced-motion adapter selection
- Confirm build state:
- source changes reflected in
dist - consuming app restarted when needed
Current Tests
src/hooks/__tests__/settleUtils.test.tssrc/hooks/__tests__/scrollMargin.test.tssrc/hooks/__tests__/useBodyScrollLock.test.tsxsrc/hooks/__tests__/useConstrainedScrollLock.test.tssrc/hooks/__tests__/useHiddenTargetFallback.test.tsxsrc/hooks/__tests__/useTourHud.test.tsxsrc/hooks/__tests__/useTourOverlay.test.tsxsrc/hooks/__tests__/waitForPredicate.test.tssrc/components/__tests__/TourFocusManager.test.tsxsrc/components/__tests__/TourPopoverPortal.test.tssrc/components/__tests__/OverlayBackdrop.test.tsxsrc/components/__tests__/overlayPath.test.tssrc/motion/__tests__/animationAdapter.test.tssrc/motion/__tests__/useHudMotion.test.tsx
When changing behavior:
- add or update deterministic tests around the changed path
- prefer fake timers for time-gated transitions
- validate both overlay and popover when changing handoff policy
AI Agent Skills (TanStack Intent)
This package ships Agent Skills via @tanstack/intent, so AI coding assistants (Claude Code, Cursor, Copilot, etc.) automatically understand how to use Flowsterix.
For End Users
After installing @flowsterix/react, run:
npx @tanstack/intent installThis discovers the skills bundled in the package and wires them into your agent config (CLAUDE.md, .cursorrules, etc.). Re-run after npm update to pick up new and updated skills.
For Maintainers
Skills live in packages/react/skills/ and are included in the npm tarball via the files field.
- Validate skills:
pnpm intent:validate - Check staleness:
pnpm intent:stale - Update skills when docs in
docs/guides/change — each skill'smetadata.sourcestracks which docs it was derived from.
Skill Index
| Skill | Description |
|-------|-------------|
| getting-started | Installation, first tour, CSS setup |
| flow-definitions | Steps, targets, advance rules, waitFor |
| react-api | TourProvider, hooks, TourHUD, DevTools |
| lifecycle-hooks | onEnter/onResume/onExit patterns |
| routing | Route gating, 4 router adapters |
| dialog-integration | Radix dialog integration |
| mobile-and-accessibility | Mobile drawer, i18n, a11y |
| storage-and-versioning | Storage adapters, versions, migrations |
Release and Maintenance Checklist
- Implement code changes and tests.
- Run:
pnpm --filter @flowsterix/react testpnpm --filter @flowsterix/react typecheckpnpm --filter @flowsterix/react build
- Update
CHANGELOG.md. - Update this README when:
- exports change
- concepts or invariants change
- tuning constants/heuristics change
- Validate at least one real consuming app path.
