Step Types
TypeScript interfaces for StepConfig, StepTarget, StepPlacement, and step-level configuration in User Tour Kit tours
Step Types
TourStep
interface TourStep<T = unknown> {
id: string;
target: string | HTMLElement | (() => HTMLElement | null);
title?: string;
content?: ReactNode;
placement?: Placement;
offset?: number | { x: number; y: number };
spotlight?: SpotlightConfig | boolean;
scroll?: ScrollConfig | boolean;
beforeEnter?: (context: StepContext) => void | Promise<void>;
afterEnter?: (context: StepContext) => void;
beforeLeave?: (context: StepContext) => void | Promise<void>;
afterLeave?: (context: StepContext) => void;
data?: T;
}StepContext
interface StepContext {
step: TourStep;
index: number;
targetElement: HTMLElement | null;
isFirst: boolean;
isLast: boolean;
direction: 'forward' | 'backward';
}Target Types
The target property accepts multiple types:
// CSS selector
const step1: TourStep = {
id: 'step-1',
target: '#my-button',
};
// Direct element reference
const step2: TourStep = {
id: 'step-2',
target: document.getElementById('my-button')!,
};
// Function (for dynamic elements)
const step3: TourStep = {
id: 'step-3',
target: () => document.querySelector('.dynamic-element'),
};Generic Step Data
interface MyStepData {
videoUrl?: string;
actionRequired?: boolean;
}
const step: TourStep<MyStepData> = {
id: 'video-step',
target: '#player',
title: 'Watch the video',
data: {
videoUrl: 'https://example.com/video.mp4',
actionRequired: true,
},
};Interactive Steps
interactive
When set to true, allows clicks to pass through the tour overlay to interact with page elements within the spotlight area. Essential for steps that require user interaction with buttons, forms, or other clickable elements.
Type: boolean
Default: false
<TourStep
id="role-select"
target="#role-buttons"
title="Choose Your Role"
content="Click a button below to select your path"
interactive // Allows clicking buttons within the spotlight
onNext={null} // Disable Next button - user must click a role
onAction={{
developer: 'dev-track',
designer: 'design-track',
}}
/>Without interactive={true}, the overlay blocks all clicks to page elements, even within the spotlight area.
Branching Navigation
User Tour Kit supports dynamic branching, allowing tours to adapt based on user choices. These props control how navigation flows between steps.
onAction
Defines named actions that can be triggered from step content using the useBranch hook. Each action maps to a branch target.
Type: Record<string, Branch>
<TourStep
id="feature-select"
target="#features"
interactive
onNext={null}
onAction={{
analytics: 'analytics-intro', // Navigate to step by ID
reports: { tour: 'reports-tour' }, // Switch to different tour
skip: 'complete', // Complete the tour
}}
/>Branch targets can be:
- Step ID (
string): Navigate to a specific step - Step index (
number): Navigate by index - Special keywords:
'next','prev','complete','skip','restart' - Cross-tour:
{ tour: 'other-tour', step?: 'step-id' } - Skip steps:
{ skip: 2 }- Jump forward 2 steps - Delayed:
{ wait: 1000, then: 'next-step' }- Wait before navigating - Stay:
null- Remain on current step - Resolver function: Dynamic logic based on context
onNext
Override the default "Next" button behavior. Set to null to hide/disable the Next button.
Type: Branch | null
Default: Advances to next step in sequence
// Navigate to specific step instead of sequential next
<TourStep
id="dev-intro"
onNext="summary" // Skip to summary step
/>
// Disable Next button (require action)
<TourStep
id="role-select"
onNext={null}
onAction={{ ... }}
/>
// Conditional navigation
<TourStep
id="feature-step"
onNext={(ctx) => ctx.data.isAdvanced ? 'advanced-section' : 'basic-section'}
/>onPrev
Override the default "Previous" button behavior. Set to null to hide/disable the Previous button.
Type: Branch | null
Default: Goes to previous step in sequence
// Navigate back to a branching point
<TourStep
id="dev-intro"
onPrev="role-select" // Return to role selection
/>
// Disable Prev button
<TourStep
id="first-step"
onPrev={null}
/>Branch Types
// Static targets
type BranchTarget =
| string // Step ID
| number // Step index
| 'next' // Next sequential step
| 'prev' // Previous step
| 'complete' // Complete the tour
| 'skip' // Skip/abort the tour
| 'restart' // Restart from beginning
| BranchToTour // Switch tours
| BranchSkip // Skip N steps
| BranchWait // Delayed navigation
| null // Stay on current step
// Cross-tour navigation
interface BranchToTour {
tour: string
step?: string | number
}
// Skip multiple steps
interface BranchSkip {
skip: number
}
// Delayed navigation
interface BranchWait {
wait: number // Milliseconds
then?: BranchTarget // Target after delay
}
// Dynamic resolver
type BranchResolver = (context: BranchContext) => BranchTarget | Promise<BranchTarget>
// Branch can be static or dynamic
type Branch = BranchTarget | BranchResolverBranchContext
Context passed to resolver functions:
interface BranchContext {
tourId: string
isActive: boolean
currentStepIndex: number
currentStep: TourStep | null
totalSteps: number
data: Record<string, unknown>
action?: string // Action ID (for onAction)
actionPayload?: unknown // Payload passed with action
setData: (key: string, value: unknown) => void
}Complete Branching Example
<Tour id="onboarding">
<TourStep
id="welcome"
target="#header"
title="Welcome!"
content="Let's personalize your experience"
/>
<TourStep
id="role-select"
target="#role-buttons"
title="Select Your Role"
content="Choose your role to see relevant content"
interactive
onNext={null}
onAction={{
developer: 'dev-path',
designer: 'design-path',
manager: 'manager-path',
}}
/>
{/* Developer path */}
<TourStep
id="dev-path"
target="#api-docs"
title="API Documentation"
content="Here's where you'll find code examples"
onNext="summary"
onPrev="role-select"
/>
{/* Designer path */}
<TourStep
id="design-path"
target="#design-tools"
title="Design Tools"
content="Explore our visual editor"
onNext="summary"
onPrev="role-select"
/>
{/* Manager path */}
<TourStep
id="manager-path"
target="#analytics"
title="Analytics Dashboard"
content="Track your team's progress"
onNext="summary"
onPrev="role-select"
/>
{/* All paths converge here */}
<TourStep
id="summary"
target="#header"
title="You're All Set!"
content="Explore more features at your own pace"
onNext="complete"
/>
</Tour>See the Branching Guide for more patterns and examples.