Walter
Product tours like a badass.
Walter White icon by Icons8
- Define tour content with simple YAML files, in any/many languages.
- Organize tours by controller and action.
- Trigger tours automatically on page load or manually via JavaScript method.
- Built with the Shepherd JS library. Plays nicely with Turbolinks.
- Ships with two basic CSS themes (default & dark) — or write your own
- Show video/html content in your
Requirements
- Walter needs to know the current user to track tour views, e.g.
current_user
from Devise. - Walter is tested on Rails 5.2, 6.0, and 6.1
Installation
Add walter
to your Gemfile:
gem 'walter'
Install the gem and run the installer:
$ bundle install
$ rails generate walter:install
$ rails db:migrate
Install the JavaScript dependencies:
$ yarn add js-cookie@^2.2.0 shepherd.js@^6.0.0-beta
Require walter
in app/assets/javascripts/application.js
//= require walter
Require a CSS theme in app/assets/stylesheets/application.scss
*= require walter/theme-default
Walter provides the following themes:
theme-default
theme-dark
Update config/walter.yml
if you choose a different theme:
defaults: &defaults
:tour_options: '{ defaultStepOptions: { classes: "theme-dark" } }'
You can also write your own Shepherd theme based on Shepherd's default CSS.
Tell Walter where to insert its generated JavaScript in app/views/layouts/application.html.erb
, just before the closing body
tag:
<%= walter_tour %>
</body>
</html>
Defining your tours
Define your tours in the app/tours
directory corresponding to the views defined in your application. Its directory structure mirrors your application's controllers, and the tour files mirror your actions/views. (As of version 2.4.0, Walter respects controllers organized into modules.)
app/
└── tours/
├── admin/
│ └── articles/
│ └── edit.en.yml
├── blog/
│ ├── show.en.yml
│ └── show.es.yml
└── articles/
├── index.en.yml
├── index.es.yml
├── show.en.yml
└── show.es.yml
For example, per above, when a Spanish-speaking user visits /articles/
, they'll see the tours defined by config/tours/articles/index.es.yml
.
(Note: You must specify a locale in the filename, even if you're only supporting one language.)
Tour content
Within a tour file, each tour is composed of a series of steps. A step may have a title
and must have text
. You may attach a step to a particular element on the page, and place the callout in a particular position.
In this example, we define a tour called "intro" with 3 steps:
intro:
steps:
1:
text: "Welcome to your dashboard! This is where we'll highlight key information to manage your day."
2:
title: "Events"
text: "If you're participating in any events today, we'll show that here."
attachTo:
element: ".dashboard-events"
placement: "right"
3:
title: "Search"
text: "You can find anything else by using the search bar."
attachTo:
element: ".navbar-primary form"
placement: "bottom"
Walter takes care of which buttons should appear with each step:
- "Later" and "Continue" buttons on the first step
- "Exit", "Back" and "Continue" buttons on intermediate steps
- "Done" button on the last step
When you specify an attachTo
element, use the placement
option to choose where the callout should appear relative to that element:
bottom
/bottom center
bottom left
bottom right
center
/middle
/middle center
left
/middle left
right
/middle right
top
/top center
top left
top right
Walter tries to be helpful when your tour steps attach to page elements that are missing:
- If your first step is attached to a particular element, and that element is not present on the page, the tour won't start. (#28)
- If your tour has an intermediate step attached to a missing element, Walter will skip that step and automatically show the next. (#6)
Automatic vs. manual tours
By default, Walter will automatically start a tour that the current user hasn't seen yet.
You can instead define a tour to be triggered manually using the trigger
option:
walkthrough:
trigger: "manual"
steps:
1:
text: "This walkthrough will show you how to..."
This tour will not start automatically; instead, use the Walter.startTour
method with the tour name:
<button id="startTour">Start tour</button>
<script>
document.querySelector("#startTour").addEventListener("click", function() {
Walter.startTour("walkthrough"));
});
</script>
...or if you happen to use jQuery:
<script>
$("#startTour").on("click", function() { Walter.startTour('walkthrough'); })
</script>
Testing your tours
Walter loads tour definitions once when you start your server. Restart your server to see tour changes.
If you'd like to run JavaScript integrations tests without the Walter tours getting in the way, clear the Walter configuration in your test helper, e.g.
Rails.application.configure do
config.walter.tours = {}
end