A Driver.js integration for Streamlit - add beautiful, interactive guided tours to your Streamlit apps with a single Python call.
- 🔗 Bind tour steps to any Streamlit widget by its
key - 🪟 Element-free info steps - show contextual popups not anchored to any component
- ✅ One-time tours - automatically skip tours the user has already completed (via
localStorage) - ↩️ State feedback - know exactly when a tour was finished, dismissed, or skipped
- 🎨 Configurable - control overlay opacity, animations, progress indicators, and popover alignment
pip install streamlit-tourOr in a more modern way:
uv add streamlit-tourimport streamlit as st
from streamlit_tour import Tour
st.title("My App")
st.text_input("Name", key="name_input")
if st.button("Start Tour"):
Tour.start(
steps=[
Tour.bind("name_input", title="Your Name", desc="Enter your name here."),
Tour.info(title="That's it!", desc="You're ready to go."),
]
)Launches the tour. Call this inside any conditional block (e.g. a button click).
result = Tour.start(
steps=[...],
show_progress=True, # Show "Step 1/3" counter
animate=True, # Animate transitions between steps
overlay_opacity=0.75, # Background overlay darkness (0.0–1.0)
one_time_tour=False, # If True, skip the tour after first completion
key="my_tour", # Unique key - change it for each tour
)Return value - a dict with the tour's final state:
| Key | Type | Description |
|---|---|---|
currentStep |
int |
Last step index the user reached |
dismissed |
bool |
True if the user closed the tour before finishing |
finished |
bool |
True if the user completed all steps |
skipped |
bool |
True if the tour was skipped (one-time, already seen) |
Attaches a tour step to a Streamlit widget via its key.
Tour.bind(
key="my_widget_key", # Must match the widget's key= argument
title="Step Title",
desc="Step description text.",
side="bottom", # "top" | "bottom" | "left" | "right" (optional)
align="center", # "start" | "center" | "end" (optional)
)How it works:
Tour.bindresolves the widget using Streamlit's.st-key-<key>CSS class, which is automatically injected on any widget that has akey=argument.
Creates a floating step with no element anchor - useful for introductory or summary slides.
Tour.info(
title="Welcome!",
desc="This tour will walk you through the main features of this app.",
)Set one_time_tour=True to automatically skip the tour for users who have already seen it. Completion is tracked in the browser's localStorage using the tour's key.
Tour.start(
steps=[...],
one_time_tour=True,
key="onboarding_tour", # Must be unique and stable across reruns
)To reset the tour (e.g. for testing), clear localStorage in your browser's DevTools, or use a different key.
Check out example.py file for a complete example of usage.
- Always provide a
keywhen usingone_time_tour=Trueor when you have multiple tours on the same page. - Widgets must have a
key=argument forTour.bind()to locate them. Anonymous widgets (nokey) are not bindable. - Re-triggering a tour: Change the
keyvalue between Streamlit reruns to force the tour to restart. - Column layouts: Use
sideandalignonTour.bind()to control which side the popover appears on narrow widgets.
- Better output - make the Tour returns an object instead of a simple dict
- Tabs and Pages - make the Tour navigate between tabs and pages (maybe with an intermediate Python actions ?)
-
Tour.reset(key)- a utility function to clear the one-time-tour flag fromlocalStorage - Step grouping - define multiple named tours and selectively launch them
- Theme support - CSS variable overrides to match Streamlit's light/dark mode
- Driver.js parameters - implement all the other Driver.js options
