Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 114 additions & 78 deletions demo/js/welcome.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,107 +23,139 @@
}
},
classPrefix: prefix,
// This should add the first tour step
steps: [
{
text: '\n <p>\n Shepherd is a JavaScript library for guiding users through your app.\n It uses <a href="https://atomiks.github.io/tippyjs//" data-test-tippy-link>Tippy.js</a>,\n another open source library, to render dialogs for each tour "step".\n </p>\n \n <p>\n Among many things, Tippy makes sure your steps never end up off screen or cropped by an overflow.\n (Try resizing your browser to see what we mean.)\n </p>\n <p>\n It also offers a robust API for styling animations of steps\n as they enter and exit the view.\n </p>',
attachTo: {
element: '.hero-welcome',
on: 'bottom'
},
buttons: [
{
action() {
return this.cancel();
},
secondary: true,
text: 'Exit'
},
{
action() {
return this.next();
},
text: 'Next'
}
],
id: 'welcome'
}
],
styleVariables: {
shepherdThemePrimary: '#00213b',
shepherdThemeSecondary: '#e5e5e5'
},
useModalOverlay: true
});
shepherd.addStep({
text: '\n <p>\n Shepherd is a JavaScript library for guiding users through your app.\n It uses <a href="https://atomiks.github.io/tippyjs//" data-test-tippy-link>Tippy.js</a>,\n another open source library, to render dialogs for each tour "step".\n </p>\n \n <p>\n Among many things, Tippy makes sure your steps never end up off screen or cropped by an overflow.\n (Try resizing your browser to see what we mean.)\n </p>\n <p>\n It also offers a robust API for styling animations of steps\n as they enter and exit the view.\n </p>',
attachTo: {
element: '.hero-welcome',
on: 'bottom'
},
buttons: [
{
action: shepherd.cancel,
secondary: true,
text: 'Exit'

// These steps should be added via `addSteps`
const steps = [
{
title: 'Including',
text: 'Including Shepherd is easy! Just include shepherd.js. The styles are bundled with the JS.',
attachTo: {
element: '.hero-including',
on: 'bottom'
},
{
action: shepherd.next,
text: 'Next'
}
],
id: 'welcome'
});
shepherd.addStep({
title: 'Including',
text: 'Including Shepherd is easy! Just include shepherd.js. The styles are bundled with the JS.',
attachTo: {
element: '.hero-including',
on: 'bottom'
buttons: [
{
action() {
return this.back();
},
secondary: true,
text: 'Back'
},
{
action() {
return this.next();
},
text: 'Next'
}
],
id: 'including'
},
buttons: [
{
action: shepherd.back,
secondary: true,
text: 'Back'
{
title: 'Creating a Shepherd Tour',
text: 'Creating a Shepherd tour is easy. too! ' + 'Just create a \`Tour\` instance, and add as many steps as you want.',
attachTo: {
element: '.hero-example',
on: 'right'
},
{
action: shepherd.next,
text: 'Next'
}
],
id: 'including'
});
shepherd.addStep({
title: 'Creating a Shepherd Tour',
text: 'Creating a Shepherd tour is easy. too! ' + 'Just create a \`Tour\` instance, and add as many steps as you want.',
attachTo: {
element: '.hero-example',
on: 'right'
},
buttons: [
{
action: shepherd.back,
secondary: true,
text: 'Back'
},
{
action: shepherd.next,
text: 'Next'
}
],
id: 'creating'
});
shepherd.addStep({
title: 'Attaching to Elements',
text: 'Your tour steps can target and attach to elements in DOM (like this step).',
attachTo: {
element: '.hero-example',
on: 'left'
buttons: [
{
action() {
return this.back();
},
secondary: true,
text: 'Back'
},
{
action() {
return this.next();
},
text: 'Next'
}
],
id: 'creating'
},
buttons: [
{
action: shepherd.back,
secondary: true,
text: 'Back'
{
title: 'Attaching to Elements',
text: 'Your tour steps can target and attach to elements in DOM (like this step).',
attachTo: {
element: '.hero-example',
on: 'left'
},
{
action: shepherd.next,
text: 'Next'
}
],
id: 'attaching'
});
buttons: [
{
action() {
return this.back();
},
secondary: true,
text: 'Back'
},
{
action() {
return this.next();
},
text: 'Next'
}
],
id: 'attaching'
}
];

shepherd.addSteps(steps);

// This should add steps after the ones added with `addSteps`
shepherd.addStep({
title: 'Centered Shepherd Element',
text: 'But attachment is totally optional!\n Without a target, a tour step will create an element that\'s centered within the view. Check out the <a href="https://shepherdjs.dev/docs/">documentation</a> to learn more.',
buttons: [
{
action: shepherd.back,
action() {
return this.back();
},
secondary: true,
text: 'Back'
},
{
action: shepherd.next,
action() {
return this.next();
},
text: 'Next'
}
],
id: 'centered-example'
});

shepherd.addStep({
title: 'Learn more',
text: 'Star Shepherd on Github so you remember it for your next project',
Expand All @@ -133,12 +165,16 @@
},
buttons: [
{
action: shepherd.back,
action() {
return this.back();
},
secondary: true,
text: 'Back'
},
{
action: shepherd.next,
action() {
return this.next();
},
text: 'Done'
}
],
Expand Down
9 changes: 8 additions & 1 deletion docs-src/tutorials/02-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ const myTour = new Shepherd.Tour(options);
- `confirmCancelMessage`: The message to display in the confirm dialog
- `defaultStepOptions`: Default options for Steps created through `addStep`
- `modalContainer` An optional container element for the modal. If not set, the modal will be appended to `document.body`.
- `steps`: An array of Step instances to initialize the tour with.
- `steps`: An array of step options objects or Step instances to initialize the tour with.
- `tourName`: An optional "name" for the tour. This will be appended to the the tour's
dynamically generated `id` property -- which is also set on the `body` element as the `data-shepherd-active-tour` attribute whenever the tour becomes active.
- `useModalOverlay`: Whether or not steps should be placed above a darkened modal overlay. If true, the overlay will create an opening around the target element so that it can remain interactive.
Expand Down Expand Up @@ -182,6 +182,13 @@ the step will execute. For example:
- `classes`: Extra classes to apply to the `<a>`
- `secondary`: A boolean, that when true, adds a `shepherd-button-secondary` class to the button
- `action`: A function executed when the button is clicked on
It is automatically bound to the `tour` the step is associated with, so things like `this.next` will
work inside the action. You can use action to skip steps or navigate to specific steps, with something like:
```javascript
action() {
return this.show('some_step_name');
}
```
- `events`: A hash of events to bind onto the button, for example `{'mouseover': function(){}}`. Adding a click event to `events` when you
already have an `action` specified is not supported.
You can use `events` to skip steps or navigate to specific steps, with something like:
Expand Down
11 changes: 8 additions & 3 deletions src/js/components/shepherd-content/shepherd-footer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,19 @@ export default class ShepherdFooter extends Component {
const { buttons } = step.options;

return <footer className={styles.footer.trim()}>
{this._addButtons(buttons, classPrefix, styles)}
{this._addButtons(buttons, classPrefix, step, styles)}
</footer>;
}

_addButtons(buttons, classPrefix, styles) {
_addButtons(buttons, classPrefix, step, styles) {
if (buttons) {
return buttons.map((config) => {
return <ShepherdButton classPrefix={classPrefix} config={config} styles={styles}/>;
return <ShepherdButton
classPrefix={classPrefix}
config={config}
step={step}
styles={styles}
/>;
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ const { Component } = preact;

export default class ShepherdButton extends Component {
render(props) {
const { classPrefix, config, styles } = props;
const { classPrefix, config, step, styles } = props;
const { action, classes, secondary, text } = config;

return <button
className={(classes || '') + styles.button + (secondary ? ` ${classPrefix}shepherd-button-secondary` : '')}
onClick={action}
onClick={action ? action.bind(step.tour) : null}
tabindex='0'>
{text}
</button>;
Expand Down
8 changes: 5 additions & 3 deletions src/js/step.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,13 @@ export class Step extends Evented {
* When the promise resolves, the rest of the `show` code for the step will execute.
* @param {Object[]} options.buttons An array of buttons to add to the step. These will be rendered in a
* footer below the main body text.
* @param {function} options.buttons.button.action A function executed when the button is clicked on
* @param {function} options.buttons.button.action A function executed when the button is clicked on.
* It is automatically bound to the `tour` the step is associated with, so things like `this.next` will
* work inside the action.
* You can use action to skip steps or navigate to specific steps, with something like:
* ```js
* action: function() {
* return Shepherd.activeTour.show('some_step_name');
* action() {
* return this.show('some_step_name');
* }
* ```
* @param {string} options.buttons.button.classes Extra classes to apply to the `<a>`
Expand Down
19 changes: 17 additions & 2 deletions src/js/tour.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class Tour extends Evented {
* mousewheel, arrow keys, etc. You may want to use this to ensure you are driving the scroll position with the tour.
* @param {HTMLElement} options.modalContainer An optional container element for the modal.
* If not set, the modal will be appended to `document.body`.
* @param {Step[]} options.steps An array of Step instances to initialize the tour with
* @param {object[] | Step[]} options.steps An array of step options objects or Step instances to initialize the tour with
* @param {object} options.styleVariables An object hash of style variables to override
* @param {string} options.tourName An optional "name" for the tour. This will be appended to the the tour's
* dynamically generated `id` property -- which is also set on the `body` element as the `data-shepherd-active-tour` attribute
Expand All @@ -62,7 +62,8 @@ export class Tour extends Evented {
this.options = options;
this.classPrefix = this.options ? normalizePrefix(this.options.classPrefix) : '';
this.styles = generateStyles(options);
this.steps = this.options.steps || [];
this.steps = [];
this.addSteps(this.options.steps);

// Pass these events onto the global Shepherd object
const events = ['active', 'cancel', 'complete', 'inactive', 'show', 'start'];
Expand Down Expand Up @@ -111,6 +112,20 @@ export class Tour extends Evented {
return step;
}

/**
* Add multiple steps to the tour
* @param {Array<object> | Array<Step>} steps The steps to add to the tour
*/
addSteps(steps) {
if (Array.isArray(steps)) {
steps.forEach((step) => {
this.addStep(step);
});
}

return this;
}

/**
* Go to the previous step in the tour
*/
Expand Down
8 changes: 8 additions & 0 deletions src/types/step.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ declare namespace Step {
interface StepOptionsButton {
/**
* A function executed when the button is clicked on
* It is automatically bound to the `tour` the step is associated with, so things like `this.next` will
* work inside the action.
* You can use action to skip steps or navigate to specific steps, with something like:
* ```js
* action() {
* return this.show('some_step_name');
* }
* ```
*/
action?: (() => void);

Expand Down
9 changes: 7 additions & 2 deletions src/types/tour.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ declare class Tour extends Evented {
*/
addStep(options: Step | Step.StepOptions): Step;

/**
* Add multiple steps to the tour
*/
addSteps(steps: Array<object> | Array<Step>): Tour;

/**
* Go to the previous step in the tour
*/
Expand Down Expand Up @@ -103,9 +108,9 @@ declare namespace Tour {
defaultStepOptions?: Step.StepOptions;

/**
* An array of Step instances to initialize the tour with
* An array of step options objects or Step instances to initialize the tour with
*/
steps?: Step[];
steps?: Array<object> | Array<Step>;

/**
* An object hash of style variables to override
Expand Down
Loading