maspotlighttour/API_Reference.md

31 KiB

MASpotlightTour API Reference

Complete API documentation for the MASpotlightTour library.

Table of Contents


Namespace

using MarketAlly.SpotlightTour.Maui;

XAML namespace:

xmlns:tour="clr-namespace:MarketAlly.SpotlightTour.Maui;assembly=MarketAlly.SpotlightTour.Maui"

OnboardingHost

The main host control that orchestrates the onboarding tour experience. Add this as an overlay on your page to enable spotlight tours.

Inheritance: GridOnboardingHost

Properties

Display & Mode Properties

Property Type Default Description
DisplayMode TourDisplayMode SpotlightWithCallout The display mode for the tour.
Theme TourTheme Light Visual theme (Light, Dark, or System).
TourFlowDirection FlowDirection MatchParent RTL support: MatchParent, LeftToRight, or RightToLeft.
AnimationsEnabled bool true Whether animations are enabled.
AnimationDuration uint 250 Animation duration in milliseconds.

Overlay Properties

Property Type Default Description
DimOpacity double 0.6 Opacity of the dimmed overlay (0.0 - 1.0).
DimColor Color Colors.Black Color of the dimmed overlay.

Callout Properties

Property Type Default Description
CalloutPositionMode CalloutPositionMode Following Positioning strategy for the callout card.
CalloutCorner CalloutCorner BottomLeft Corner to use when CalloutPositionMode is FixedCorner.
CalloutCornerMargin double 16.0 Margin from screen edge when using corner positioning.

Navigator Properties

Property Type Default Description
ShowCornerNavigator bool true Whether to show the corner navigator control.
CornerNavigatorPlacement CornerNavigatorPlacement BottomRight Position of the corner navigator.
ShowSkipButton bool true Whether to show the skip/done button in navigator.
ShowArrow bool true Whether to show the arrow indicator pointing to spotlight.

Auto Features

Property Type Default Description
AutoStartDelay int 0 Delay in ms before auto-starting. 0 = disabled.
AutoStartGroup string? null Group to use for auto-start.
AutoAdvanceDelay int 0 Delay in ms before auto-advancing. 0 = disabled.
AutoLoop int 0 Number of times to repeat the tour. 0 = disabled.

Intro View

Property Type Default Description
IntroView View? null Custom intro/welcome view displayed before tour starts.
ShowIntro bool true Controls whether intro view is displayed. Set to false to skip intro (useful for returning users).
AllowTapAnywhereToDismissIntro bool false When true, tapping anywhere on the dimmed overlay while intro is shown will skip the tour.

Read-Only Properties

Property Type Description
IsRunning bool Whether a tour is currently running.
CurrentStepIndex int Current step index (0-based). -1 if not running.
TotalSteps int Total number of steps in the tour.
CurrentStep OnboardingStep? Current step, or null if no tour is running.
IsShowingIntro bool Whether the intro view is currently displayed.

Methods

Starting Tours

Task<TourResult> StartTourAsync(VisualElement root, string? group = null)

Starts the onboarding tour by scanning for tagged elements. Returns when the tour ends.

Parameters:

  • root: The root element to scan (typically this.Content or a layout).
  • group: Optional group filter. If null, includes all steps.

Returns: TourResult indicating how the tour ended.


Task<TourResult> StartTourFromStepAsync(VisualElement root, string stepKey, string? group = null)

Starts the tour from a specific step identified by its key.

Parameters:

  • root: The root element to scan.
  • stepKey: The step key to start from.
  • group: Optional group filter.

Returns: TourResult indicating how the tour ended.


Task<TourResult> StartTourWithIntroAsync(VisualElement root, string? group = null, bool showIntro = true)

Starts the tour, optionally showing the intro view first.

Parameters:

  • root: The root element to scan.
  • group: Optional group filter.
  • showIntro: Whether to show the intro view (if configured).

Returns: TourResult indicating how the tour ended.

Navigation

Task GoToStepAsync(int index)

Navigates to a specific step by index.


void GoToNextStep()

Advances to the next step. Completes the tour if on the last step.


void GoToPreviousStep()

Returns to the previous step. Does nothing if on the first step.

Ending Tours

void CompleteTour()

Completes the tour (user finished all steps). Triggers TourCompleted event.


void SkipTour()

Skips/cancels the tour. Triggers TourSkipped event.


void StopTour()

Stops any currently running tour. Sets result to Cancelled.

Intro View

void DisplayIntroView()

Displays the intro view. Called automatically by StartTourWithIntroAsync when ShowIntro property is true.


void DismissIntro()

Dismisses the intro view and continues with the tour.

Events

Event Args Description
TourStarted EventArgs Raised when the tour starts.
TourCompleted EventArgs Raised when the user completes all steps.
TourSkipped EventArgs Raised when the user skips the tour.
TourEnded EventArgs Raised when the tour ends (any reason).
StepEntering StepActionEventArgs Raised before entering a step. Async. Can set Skip = true.
StepEntered StepActionEventArgs Raised after step is fully visible (after animations).
StepLeaving StepActionEventArgs Raised before leaving the current step. Async.
StepChanged OnboardingStepEventArgs Raised when moving to a new step.
IntroShown EventArgs Raised when the intro view is shown.
IntroDismissed EventArgs Raised when the intro view is dismissed.

Step Action Registration

void RegisterStepEnteringAction(string stepKey, Func<OnboardingStep, CancellationToken, Task> action)

Registers an action to execute when entering a specific step (by StepKey). The action runs before the spotlight animates to the step.


void RegisterStepLeavingAction(string stepKey, Func<OnboardingStep, CancellationToken, Task> action)

Registers an action to execute when leaving a specific step (by StepKey). The action runs before navigating away.


bool UnregisterStepEnteringAction(string stepKey)

Removes a registered entering action for a step. Returns true if the action was removed.


bool UnregisterStepLeavingAction(string stepKey)

Removes a registered leaving action for a step. Returns true if the action was removed.


void ClearStepActions()

Clears all registered step actions (both entering and leaving).

Usage Example

<tour:OnboardingHost
    x:Name="TourHost"
    DisplayMode="SpotlightWithCallout"
    Theme="System"
    ShowCornerNavigator="True"
    CornerNavigatorPlacement="Auto"
    CalloutPositionMode="AutoCorner"
    DimOpacity="0.7"
    AnimationDuration="300" />
var result = await TourHost.StartTourAsync(this.Content);
if (result == TourResult.Completed)
{
    // Tour completed successfully
}

Onboarding (Attached Properties)

Static class providing attached properties for tagging UI elements as onboarding/tour steps.

Attached Properties

Identification

Property Type Default Description
StepKey string? null Unique key identifying the step. Falls back to AutomationId if not set.
Group string? null Group name for organizing multiple tours.
Order int 0 Sequence number within the group. Lower numbers appear first.

Content

Property Type Default Description
Title string? null Title text displayed in the callout.
Description string? null Description text displayed in the callout.

Spotlight Appearance

Property Type Default Description
SpotlightEnabled bool true Whether this element participates in spotlight cutouts.
SpotlightShape SpotlightShape RoundedRectangle Shape of the spotlight cutout.
SpotlightPadding Thickness 8 Padding around the target element.
SpotlightCornerRadius double 8.0 Corner radius for RoundedRectangle shape.

Behavior

Property Type Default Description
Placement CalloutPlacement Auto Where to place the callout relative to this element.
TapBehavior SpotlightTapBehavior None Behavior when user taps the spotlight.

Step Actions

Property Type Default Description
OnEntering Func<OnboardingStep, CancellationToken, Task>? null Action to execute when entering this step. Runs before spotlight animation.
OnLeaving Func<OnboardingStep, CancellationToken, Task>? null Action to execute when leaving this step. Runs before navigating away.

Static Methods

string? GetEffectiveStepKey(BindableObject view)

Gets the step key, falling back to AutomationId if StepKey is not set.


bool IsOnboardingStep(BindableObject view)

Returns true if the element is tagged as an onboarding step (has StepKey, Title, or Description).

XAML Usage

<Button
    Text="Click Me"
    tour:Onboarding.StepKey="my-button"
    tour:Onboarding.Title="Button Title"
    tour:Onboarding.Description="This is the button description."
    tour:Onboarding.Order="1"
    tour:Onboarding.Group="main-tour"
    tour:Onboarding.SpotlightShape="RoundedRectangle"
    tour:Onboarding.SpotlightPadding="12"
    tour:Onboarding.SpotlightCornerRadius="16"
    tour:Onboarding.Placement="Bottom"
    tour:Onboarding.TapBehavior="Advance" />

C# Usage

// Set properties programmatically
Onboarding.SetStepKey(myButton, "my-button");
Onboarding.SetTitle(myButton, "Button Title");
Onboarding.SetDescription(myButton, "Description text");
Onboarding.SetOrder(myButton, 1);
Onboarding.SetSpotlightShape(myButton, SpotlightShape.Circle);

// Read properties
var key = Onboarding.GetStepKey(myButton);
var title = Onboarding.GetTitle(myButton);

// Set step actions (async actions that run when entering/leaving this step)
Onboarding.SetOnEntering(myButton, async (step, cancellationToken) =>
{
    // Prepare UI before spotlight appears (e.g., switch tabs, open drawer)
    MainTabView.SelectedIndex = 2;
    await Task.Delay(100);
});

Onboarding.SetOnLeaving(myButton, async (step, cancellationToken) =>
{
    // Cleanup when leaving this step
});

OnboardingStep

Represents a single step in an onboarding tour. Created automatically from tagged elements or can be created programmatically.

Properties

Property Type Description
Target VisualElement The target visual element for this step. Required.
StepKey string? Unique key identifying this step.
Title string? Title text displayed in the callout.
Description string? Description text displayed in the callout.
Order int Sequence number within the group.
Group string? Group name for organizing multiple tours.
SpotlightEnabled bool Whether spotlight cutout is enabled. Default: true.
Placement CalloutPlacement Callout placement relative to spotlight. Default: Auto.
SpotlightShape SpotlightShape Shape of the spotlight cutout. Default: RoundedRectangle.
SpotlightPadding Thickness Padding around target. Default: 8.
SpotlightCornerRadius double Corner radius for rounded rectangle. Default: 8.0.
TapBehavior SpotlightTapBehavior Behavior when tapping spotlight. Default: None.
OnEntering Func<OnboardingStep, CancellationToken, Task>? Action to execute when entering this step.
OnLeaving Func<OnboardingStep, CancellationToken, Task>? Action to execute when leaving this step.

Static Methods

OnboardingStep FromElement(VisualElement element)

Creates an OnboardingStep from a tagged VisualElement by reading its attached properties.

Usage Example

// Create from element
var step = OnboardingStep.FromElement(myButton);

// Create programmatically
var step = new OnboardingStep
{
    Target = myButton,
    StepKey = "welcome",
    Title = "Welcome",
    Description = "This is the welcome step.",
    Order = 1,
    SpotlightShape = SpotlightShape.RoundedRectangle
};

OnboardingScanner

Static utility class for scanning the visual tree to find elements tagged with onboarding properties.

Methods

IReadOnlyList<OnboardingStep> FindSteps(Element root, string? group = null)

Finds all onboarding steps within the given root element.

Parameters:

  • root: The root element to scan.
  • group: Optional group filter. If null, returns all steps.

Returns: Ordered list of OnboardingStep objects.


OnboardingStep? FindStepByKey(Element root, string stepKey)

Finds a specific step by its key.

Parameters:

  • root: The root element to scan.
  • stepKey: The step key to find (case-insensitive).

Returns: The matching OnboardingStep or null if not found.


IReadOnlyList<string> GetGroups(Element root)

Gets all unique group names found in the visual tree.

Returns: Alphabetically sorted list of group names.


int CountSteps(Element root, string? group = null)

Counts the total number of steps, optionally filtered by group.

Usage Example

// Find all steps
var allSteps = OnboardingScanner.FindSteps(this.Content);

// Find steps in a specific group
var basicSteps = OnboardingScanner.FindSteps(this.Content, "basics");

// Find a specific step
var welcomeStep = OnboardingScanner.FindStepByKey(this.Content, "welcome");

// Get all groups
var groups = OnboardingScanner.GetGroups(this.Content);
// Returns: ["advanced", "basics", "settings"]

// Count steps
var totalCount = OnboardingScanner.CountSteps(this.Content);
var groupCount = OnboardingScanner.CountSteps(this.Content, "basics");

Enumerations

TourDisplayMode

Specifies the display mode for the onboarding tour.

Value Description
SpotlightWithCallout Full experience: dimmed overlay + spotlight cutout + callout card with nav buttons.
CalloutOnly Callout cards only - no dimming. Good for light-touch guidance.
SpotlightWithInlineLabel Dimmed overlay with spotlight, inline labels instead of callout card. Use with corner navigator.

TourTheme

Specifies the visual theme for tour components.

Value Description
Light Light theme with white backgrounds and dark text.
Dark Dark theme with dark backgrounds and light text.
System Automatically follows the system theme.

CalloutPlacement

Specifies where the callout card is positioned relative to the spotlight.

Value Description
Auto Automatically determine placement based on available space.
Top Position callout above the spotlight.
Bottom Position callout below the spotlight.
Left Position callout to the left of the spotlight.
Right Position callout to the right of the spotlight.

CalloutPositionMode

Specifies the positioning strategy for the callout card.

Value Description
Following Callout positions relative to the highlighted element. Uses CalloutPlacement.
FixedCorner Callout stays in a fixed screen corner. Uses CalloutCorner.
AutoCorner Callout auto-positions in the corner that least interferes with the spotlight.

CalloutCorner

Specifies which screen corner for fixed/auto corner positioning.

Value Description
TopLeft Top-left corner of the screen.
TopRight Top-right corner of the screen.
BottomLeft Bottom-left corner of the screen.
BottomRight Bottom-right corner of the screen.

CornerNavigatorPlacement

Specifies the corner position for the navigator control.

Value Description
TopLeft Top-left corner of the screen.
TopRight Top-right corner of the screen.
BottomLeft Bottom-left corner of the screen.
BottomRight Bottom-right corner of the screen.
Auto Automatically positions to avoid overlapping with spotlight and callout.

SpotlightShape

Specifies the shape of the spotlight cutout.

Value Description
Rectangle Rectangular cutout matching the element bounds.
RoundedRectangle Rounded rectangle with configurable corner radius.
Circle Circular cutout centered on the element.

SpotlightTapBehavior

Specifies behavior when the user taps on the spotlighted element.

Value Description
None Tapping does nothing; only nav buttons work.
Advance Tapping advances to the next step.
Close Tapping closes/ends the tour.
AllowInteraction Allow interaction with the underlying element (pass-through).

TourResult

Specifies how a tour ended. Returned by StartTourAsync methods.

Value Description
Completed The tour completed successfully (user went through all steps).
Skipped The tour was skipped by the user.
Cancelled The tour was cancelled programmatically.
NoSteps No steps were found to show.

Events

OnboardingStepEventArgs

Event arguments for the StepChanged event.

Property Type Description
Step OnboardingStep The current step.
StepIndex int Zero-based index of the current step.
TotalSteps int Total number of steps in the tour.

Usage Example

TourHost.StepChanged += (sender, e) =>
{
    Console.WriteLine($"Now on step {e.StepIndex + 1} of {e.TotalSteps}");
    Console.WriteLine($"Title: {e.Step.Title}");
    Console.WriteLine($"Key: {e.Step.StepKey}");
};

StepActionEventArgs

Event arguments for step action events (StepEntering, StepEntered, StepLeaving).

Property Type Description
Step OnboardingStep The step being entered or left.
StepIndex int Zero-based index of the step.
TotalSteps int Total number of steps in the tour.
PreviousStepIndex int Index of the previous step (-1 if first step).
IsForward bool Whether navigation is moving forward (true) or backward (false).
Skip bool Set to true to skip this step (only applies to StepEntering).
CancellationToken CancellationToken Cancellation token for the current operation.

Step Action Usage Example

// Register action by StepKey
TourHost.RegisterStepEnteringAction("settings-tab", async (step, token) =>
{
    // Switch to settings tab before spotlight appears
    SettingsTabView.SelectedIndex = 1;
    await Task.Delay(150); // Wait for tab transition
});

// Use event for conditional skipping
TourHost.StepEntering += async (sender, e) =>
{
    // Skip premium-only steps for free users
    if (e.Step.StepKey?.StartsWith("premium-") == true && !User.IsPremium)
    {
        e.Skip = true;
    }
};

// Track when steps are viewed
TourHost.StepEntered += (sender, e) =>
{
    Analytics.Track("tour_step_viewed", new {
        step_key = e.Step.StepKey,
        step_index = e.StepIndex,
        is_forward = e.IsForward
    });
};

// Cleanup when leaving steps
TourHost.StepLeaving += async (sender, e) =>
{
    if (e.Step.StepKey == "drawer-step")
    {
        Shell.Current.FlyoutIsPresented = false;
        await Task.Delay(200);
    }
};

Complete Integration Example

XAML (MainPage.xaml)

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:tour="clr-namespace:MarketAlly.SpotlightTour.Maui;assembly=MarketAlly.SpotlightTour.Maui"
             x:Class="MyApp.MainPage"
             Title="Home">

    <Grid>
        <!-- Main Content -->
        <ScrollView>
            <VerticalStackLayout Padding="20" Spacing="16">

                <!-- Step 1: Profile Image -->
                <Border
                    StrokeShape="RoundRectangle 50"
                    WidthRequest="100"
                    HeightRequest="100"
                    HorizontalOptions="Center"
                    tour:Onboarding.StepKey="profile-image"
                    tour:Onboarding.Title="Your Profile"
                    tour:Onboarding.Description="Tap here to view and edit your profile picture."
                    tour:Onboarding.Order="1"
                    tour:Onboarding.SpotlightShape="Circle">
                    <Image Source="profile.png" Aspect="AspectFill" />
                </Border>

                <!-- Step 2: Search Bar -->
                <SearchBar
                    Placeholder="Search..."
                    tour:Onboarding.StepKey="search"
                    tour:Onboarding.Title="Quick Search"
                    tour:Onboarding.Description="Find anything in the app instantly."
                    tour:Onboarding.Order="2"
                    tour:Onboarding.SpotlightPadding="4" />

                <!-- Step 3: Feature Cards (Grouped) -->
                <Label Text="Features" FontSize="20" FontAttributes="Bold" />

                <Frame
                    BackgroundColor="#E3F2FD"
                    Padding="16"
                    CornerRadius="12"
                    tour:Onboarding.StepKey="feature-analytics"
                    tour:Onboarding.Title="Analytics Dashboard"
                    tour:Onboarding.Description="View detailed analytics and reports."
                    tour:Onboarding.Order="3"
                    tour:Onboarding.Group="features">
                    <Label Text="Analytics" FontAttributes="Bold" />
                </Frame>

                <Frame
                    BackgroundColor="#E8F5E9"
                    Padding="16"
                    CornerRadius="12"
                    tour:Onboarding.StepKey="feature-settings"
                    tour:Onboarding.Title="Settings"
                    tour:Onboarding.Description="Customize your experience."
                    tour:Onboarding.Order="4"
                    tour:Onboarding.Group="features">
                    <Label Text="Settings" FontAttributes="Bold" />
                </Frame>

                <!-- Step 4: Action Button -->
                <Button
                    Text="Get Started"
                    BackgroundColor="#007AFF"
                    TextColor="White"
                    CornerRadius="8"
                    tour:Onboarding.StepKey="get-started"
                    tour:Onboarding.Title="Ready to Go!"
                    tour:Onboarding.Description="Tap this button to begin using the app."
                    tour:Onboarding.Order="5"
                    tour:Onboarding.TapBehavior="Advance"
                    Clicked="OnGetStartedClicked" />

            </VerticalStackLayout>
        </ScrollView>

        <!-- Onboarding Host (Overlay) -->
        <tour:OnboardingHost
            x:Name="TourHost"
            DisplayMode="SpotlightWithCallout"
            Theme="System"
            ShowCornerNavigator="True"
            CornerNavigatorPlacement="Auto"
            CalloutPositionMode="AutoCorner"
            DimOpacity="0.75"
            AnimationDuration="300">

            <!-- Intro View -->
            <tour:OnboardingHost.IntroView>
                <Frame
                    BackgroundColor="White"
                    CornerRadius="20"
                    Padding="32"
                    HorizontalOptions="Center"
                    VerticalOptions="Center"
                    WidthRequest="320">
                    <VerticalStackLayout Spacing="24">
                        <Image
                            Source="app_logo.png"
                            HeightRequest="80"
                            Aspect="AspectFit" />
                        <Label
                            Text="Welcome to MyApp!"
                            FontSize="24"
                            FontAttributes="Bold"
                            HorizontalTextAlignment="Center" />
                        <Label
                            Text="Let's take a quick tour to help you get started."
                            FontSize="14"
                            TextColor="Gray"
                            HorizontalTextAlignment="Center" />
                        <Button
                            Text="Start Tour"
                            BackgroundColor="#007AFF"
                            TextColor="White"
                            CornerRadius="8"
                            Clicked="OnStartTourClicked" />
                        <Button
                            Text="Skip"
                            BackgroundColor="Transparent"
                            TextColor="Gray"
                            Clicked="OnSkipIntroClicked" />
                    </VerticalStackLayout>
                </Frame>
            </tour:OnboardingHost.IntroView>

        </tour:OnboardingHost>
    </Grid>

</ContentPage>

Code-Behind (MainPage.xaml.cs)

using MarketAlly.SpotlightTour.Maui;

namespace MyApp;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        // Subscribe to events
        TourHost.TourStarted += OnTourStarted;
        TourHost.StepChanged += OnStepChanged;
        TourHost.TourCompleted += OnTourCompleted;
        TourHost.TourSkipped += OnTourSkipped;
    }

    protected override async void OnAppearing()
    {
        base.OnAppearing();

        // Show tour for first-time users
        if (!Preferences.Get("HasCompletedTour", false))
        {
            // Small delay for page to fully load
            await Task.Delay(500);
            await StartOnboardingAsync();
        }
    }

    private async Task StartOnboardingAsync()
    {
        var result = await TourHost.StartTourWithIntroAsync(this.Content);

        if (result == TourResult.Completed)
        {
            Preferences.Set("HasCompletedTour", true);
            await DisplayAlert("All Done!", "You've completed the tour. Enjoy the app!", "OK");
        }
    }

    private void OnStartTourClicked(object sender, EventArgs e)
    {
        TourHost.DismissIntro();
    }

    private async void OnSkipIntroClicked(object sender, EventArgs e)
    {
        TourHost.SkipTour();
        await DisplayAlert("Tour Skipped", "You can restart the tour from Settings.", "OK");
    }

    private void OnTourStarted(object? sender, EventArgs e)
    {
        Console.WriteLine("Tour started!");
    }

    private void OnStepChanged(object? sender, OnboardingStepEventArgs e)
    {
        Console.WriteLine($"Step {e.StepIndex + 1}/{e.TotalSteps}: {e.Step.Title}");

        // Track analytics
        Analytics.TrackEvent("TourStep", new Dictionary<string, string>
        {
            { "StepKey", e.Step.StepKey ?? "unknown" },
            { "StepIndex", e.StepIndex.ToString() }
        });
    }

    private void OnTourCompleted(object? sender, EventArgs e)
    {
        Console.WriteLine("Tour completed!");
    }

    private void OnTourSkipped(object? sender, EventArgs e)
    {
        Console.WriteLine("Tour skipped.");
    }

    private void OnGetStartedClicked(object sender, EventArgs e)
    {
        // Handle button click
        // If tour is running, TapBehavior="Advance" will auto-advance
    }

    // Method to restart tour (e.g., from Settings)
    public async void RestartTour()
    {
        await TourHost.StartTourAsync(this.Content);
    }
}

Best Practices

1. Element Ordering

Use explicit Order values to ensure consistent step sequence:

tour:Onboarding.Order="1"
tour:Onboarding.Order="2"

2. Meaningful Step Keys

Use descriptive, unique keys for programmatic access:

tour:Onboarding.StepKey="profile-settings-button"

3. Concise Content

Keep titles short (2-5 words) and descriptions clear (1-2 sentences):

tour:Onboarding.Title="Quick Actions"
tour:Onboarding.Description="Access frequently used features with one tap."

4. Appropriate Spotlight Shapes

  • Use Circle for icons, avatars, and circular elements
  • Use RoundedRectangle for buttons, cards, and inputs
  • Use Rectangle for full-width elements or tables

Use groups to organize multiple tours:

tour:Onboarding.Group="onboarding"
tour:Onboarding.Group="new-features"
tour:Onboarding.Group="pro-tips"

6. Persist Tour Completion

Always save tour completion state:

if (result == TourResult.Completed)
{
    Preferences.Set("HasSeenTour_v1", true);
}

7. Auto-Positioning

Use Auto placement modes for responsive layouts:

CalloutPositionMode="AutoCorner"
CornerNavigatorPlacement="Auto"

Troubleshooting

Tour doesn't start

  • Ensure OnboardingHost is added as the last child (overlay)
  • Verify elements have StepKey, Title, or Description set
  • Check that the root element passed to StartTourAsync contains the tagged elements

Steps appear in wrong order

  • Verify Order values are set correctly
  • Steps with the same Order are sorted by visual tree position

Callout positioning issues

  • Try different CalloutPositionMode values
  • Increase CalloutCornerMargin if callout is too close to edges
  • Use CalloutPlacement per-element for specific positioning

Spotlight not visible

  • Check DimOpacity is greater than 0
  • Verify SpotlightEnabled is not set to false
  • Ensure the target element is visible and has non-zero dimensions

For additional support, visit the repository.