fission-onboarding 0.1.0

Guided in-app tours and spotlight onboarding for Fission applications
Documentation
  • Coverage
  • 4.84%
    3 out of 62 items documented0 out of 0 items with examples
  • Size
  • Source code size: 201.6 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 542.7 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 40s Average build duration of successful builds.
  • all releases: 40s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • zcourts

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 stable WidgetId::explicit(...) per target. Wrap the live target in OnboardingAnchor, 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 an onboarding 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.