Crates
/
fission-onboarding
fission-onboarding
v0.1.0
Guided in-app tours and spotlight onboarding for Fission applications
Install
cargo add fission-onboarding
Copy
Platform support
Declared by the crate author and captured when this directory was generated.
Android
Not declared
iOS
Not declared
Linux
Not declared
macOS
Not declared
Windows
Not declared
Web
Not declared
Terminal
Not declared
Static site
Not declared
Server-rendered
Not declared
Package metadata
crates.io
View package
Documentation
Open link
Repository
Not provided
License
MIT
Latest version
0.1.0
Downloads
0
Last updated
2026-10-09T20:01:00.591031Z
Categories
development-tools
gui
Keywords
fission
fission-framework
onboarding
spotlight
walkthrough
Published versions
0.1.0
Dependencies
Dependency metadata is not indexed yet.
README

fission-onboarding

Help people learn your app by using your app. fission-onboarding places a spotlight and a small guided callout over real Fission widgets—a button, field, result, or any other retained widget. The rest of the screen stays in place, so a first-run tour can guide an actual task instead of showing a stack of slides.
The crate supplies validated, versioned flows, stable anchors, spotlight and callout rendering, accessible controls, and host-defined styling. Your app decides when a step is complete, where to navigate, what to say, and how to save progress. It works with the Fission application model, not a browser-specific DOM tour.

Add it

[dependencies]
fission = "0.15.1"
fission-onboarding = "0.1"

Smallest working tour

This complete example highlights a real button. Clicking that button—or choosing Finish in the callout—ends the tour.
use fission::prelude::*;
use fission_onboarding::{OnboardingAnchor, OnboardingFlow, OnboardingHost, OnboardingStep};

#[derive(Clone, Debug, Default)]
struct State { finished: bool }
impl GlobalState for State {}

#[fission_reducer(FinishTour)]
fn finish_tour(state: &mut State) { state.finished = true; }

#[derive(Clone)]
struct App;
impl From<App> for Widget {
    fn from(_: App) -> Widget {
        let (ctx, view) = fission::build::current::<State>();
        let finish = ctx.bind(FinishTour, reduce_with!(finish_tour));
        let target = WidgetId::explicit("demo.create");
        let flow = OnboardingFlow::new("first-use", 1, vec![OnboardingStep {
            id: "create".into(),
            anchor: target,
            route: None,
            title: "Make your first item".into(),
            body: "Use this button to start. You can revisit the tour later.".into(),
        }]).expect("valid tour");

        let mut children = widgets![OnboardingAnchor {
            id: target,
            child: Button {
                child: Some(Text::new("Create item").into()),
                on_press: Some(finish.clone()),
                ..Default::default()
            }.into(),
        }];
        if !view.state().finished {
            children.push(OnboardingHost::new(
                "first-use", flow, 0, finish.clone(), finish,
            ).into());
        }
        Column { children, ..Default::default() }.into()
    }
}

fn main() {
    DesktopApp::<State, _>::new(App).run().expect("start app");
}

Run the checked-in copy:
cargo run --example minimal --features desktop-demo

Guide a real task

For more than one step, create an OnboardingFlow with one stableWidgetId::explicit(...) per target. Wrap the live target inOnboardingAnchor, then render OnboardingHost alongside the normal app tree. The host is presentation only; your reducers own transitions. This makes it straightforward to require a real result before enabling Continue:
let mut host = OnboardingHost::new(
    "first-task", flow, state.step,
    ctx.bind(NextStep, reduce_with!(next_step)),
    ctx.bind(FinishTour, reduce_with!(finish_tour)),
);
host.continue_enabled = state.created_item.is_some();
host.on_skip = Some(ctx.bind(SkipTour, reduce_with!(skip_tour)));
host.labels.progress = format!("Step {} of 3", state.step + 1).into();
host.style = my_app_onboarding_style(&view.env().theme);

See the complete guided-task example for a runnable three-step flow with a field, a gated task action, Back, and Skip:
cargo run --example guided_task --features desktop-demo

The optional route on a step is metadata for your app's navigation. If a target is on another screen or below a scroll viewport, navigate and call Fission's ensure_visible effect before displaying that step. The anchor must belong to a widget in the active retained tree. For responsive layouts, give each live branch its own stable anchor and choose the matching flow anchor.

Save and resume progress

fission-onboarding intentionally does not create a second persistence system. Keep the flow ID, version, current step ID, and completed/skipped state in your app's normal store. With Fission Store, use a typed StoreKey<T> in anonboarding namespace, hydrate it through a startup action, and persist each transition from reducers. On a new flow version, choose whether to restart or skip previously completed tours. Your app also decides whether Skip is offered and where a user can restart the tour.

What you control

Concern
Owner
Spotlight, anchored callout, buttons, accessible dialog
This crate
Target widgets and stable IDs
Your app
Text, translation, colours, spacing
Your app
Step conditions, navigation, scrolling
Your app
Progress storage and restart policy
Your app
The crate has no account service, analytics, network call, or product-specific state. It depends on Fission and thiserror only. Licensed MIT.
README

fission-onboarding

Help people learn your app by using your app. fission-onboarding places a spotlight and a small guided callout over real Fission widgets—a button, field, result, or any other retained widget. The rest of the screen stays in place, so a first-run tour can guide an actual task instead of showing a stack of slides.
The crate supplies validated, versioned flows, stable anchors, spotlight and callout rendering, accessible controls, and host-defined styling. Your app decides when a step is complete, where to navigate, what to say, and how to save progress. It works with the Fission application model, not a browser-specific DOM tour.

Add it

[dependencies]
fission = "0.15.1"
fission-onboarding = "0.1"

Smallest working tour

This complete example highlights a real button. Clicking that button—or choosing Finish in the callout—ends the tour.
use fission::prelude::*;
use fission_onboarding::{OnboardingAnchor, OnboardingFlow, OnboardingHost, OnboardingStep};

#[derive(Clone, Debug, Default)]
struct State { finished: bool }
impl GlobalState for State {}

#[fission_reducer(FinishTour)]
fn finish_tour(state: &mut State) { state.finished = true; }

#[derive(Clone)]
struct App;
impl From<App> for Widget {
    fn from(_: App) -> Widget {
        let (ctx, view) = fission::build::current::<State>();
        let finish = ctx.bind(FinishTour, reduce_with!(finish_tour));
        let target = WidgetId::explicit("demo.create");
        let flow = OnboardingFlow::new("first-use", 1, vec![OnboardingStep {
            id: "create".into(),
            anchor: target,
            route: None,
            title: "Make your first item".into(),
            body: "Use this button to start. You can revisit the tour later.".into(),
        }]).expect("valid tour");

        let mut children = widgets![OnboardingAnchor {
            id: target,
            child: Button {
                child: Some(Text::new("Create item").into()),
                on_press: Some(finish.clone()),
                ..Default::default()
            }.into(),
        }];
        if !view.state().finished {
            children.push(OnboardingHost::new(
                "first-use", flow, 0, finish.clone(), finish,
            ).into());
        }
        Column { children, ..Default::default() }.into()
    }
}

fn main() {
    DesktopApp::<State, _>::new(App).run().expect("start app");
}

Run the checked-in copy:
cargo run --example minimal --features desktop-demo

Guide a real task

For more than one step, create an OnboardingFlow with one stableWidgetId::explicit(...) per target. Wrap the live target inOnboardingAnchor, then render OnboardingHost alongside the normal app tree. The host is presentation only; your reducers own transitions. This makes it straightforward to require a real result before enabling Continue:
let mut host = OnboardingHost::new(
    "first-task", flow, state.step,
    ctx.bind(NextStep, reduce_with!(next_step)),
    ctx.bind(FinishTour, reduce_with!(finish_tour)),
);
host.continue_enabled = state.created_item.is_some();
host.on_skip = Some(ctx.bind(SkipTour, reduce_with!(skip_tour)));
host.labels.progress = format!("Step {} of 3", state.step + 1).into();
host.style = my_app_onboarding_style(&view.env().theme);

See the complete guided-task example for a runnable three-step flow with a field, a gated task action, Back, and Skip:
cargo run --example guided_task --features desktop-demo

The optional route on a step is metadata for your app's navigation. If a target is on another screen or below a scroll viewport, navigate and call Fission's ensure_visible effect before displaying that step. The anchor must belong to a widget in the active retained tree. For responsive layouts, give each live branch its own stable anchor and choose the matching flow anchor.

Save and resume progress

fission-onboarding intentionally does not create a second persistence system. Keep the flow ID, version, current step ID, and completed/skipped state in your app's normal store. With Fission Store, use a typed StoreKey<T> in anonboarding namespace, hydrate it through a startup action, and persist each transition from reducers. On a new flow version, choose whether to restart or skip previously completed tours. Your app also decides whether Skip is offered and where a user can restart the tour.

What you control

Concern
Owner
Spotlight, anchored callout, buttons, accessible dialog
This crate
Target widgets and stable IDs
Your app
Text, translation, colours, spacing
Your app
Step conditions, navigation, scrolling
Your app
Progress storage and restart policy
Your app
The crate has no account service, analytics, network call, or product-specific state. It depends on Fission and thiserror only. Licensed MIT.
Package metadata
crates.io
View package
Documentation
Open link
Repository
Not provided
License
MIT
Latest version
0.1.0
Downloads
0
Last updated
2026-10-09T20:01:00.591031Z
Categories
development-tools
gui
Keywords
fission
fission-framework
onboarding
spotlight
walkthrough
Published versions
0.1.0
Dependencies
Dependency metadata is not indexed yet.