shepherd.jsを使えばあなたのWebサービスに簡単にガイド(チュートリアル)を組み込める！

<p class="codepen" data-height="565" data-theme-id="0" data-default-tab="result" data-user="okumurakengo" data-slug-hash="qGNpNR" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Shepherd Sample">
  <span>See the Pen <a href="https://codepen.io/okumurakengo/pen/qGNpNR/">
  Shepherd Sample</a> by 奥村健吾 (<a href="https://codepen.io/okumurakengo">@okumurakengo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

このようにWebサービスの使い方の説明のガイドを簡単に作ることができます

【[↑のwebpack使用版のコード](https://github.com/okumurakengo/00021_shepherd)】

# Shepherd

- [github](https://github.com/shipshapecode/shepherd) (2019/05/13 現在 スター数:star2: 7407 :star2: )
- [デモページ](https://shipshapecode.github.io/shepherd/docs/welcome/)
- [ドキュメント](https://shipshapecode.github.io/shepherd/)

<img width="1142" alt="Screen Shot 2019-05-12 at 18.01.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/e6c77360-d353-982a-93a0-4f58d48fdc00.png">

## Instaration

```bash:bash
yarn add shepherd.js
#or
npm i shepherd.js
```

## webpackで動かせるサンプル

```bash
yarn init -y
yarn add -D shepherd.js webpack webpack-cli css-loader style-loader
```

```webpack.config.js
module.exports = {
    mode: "development",
    module: {
        rules: [{
            test: /\.css/,
            use: ["style-loader", "css-loader"]
        }]
    }
};
```

```src/index.js
import Shepherd from "shepherd.js";
import "shepherd.js/dist/css/shepherd-theme-default.css";

let tour = new Shepherd.Tour({
    defaultStepOptions: {
      scrollTo: true
    }
});

tour.addStep("step1", {
    title: "Hoge",
    text: "Step Hoge の説明",
    attachTo: ".hoge bottom",
    buttons: [{ text: "次へ", action: tour.next }]
});

tour.addStep("step2", {
    title: "Fuga",
    text: "Step Fuga の説明",
    attachTo: ".fuga bottom",
    buttons: [{ text: "次へ", action: tour.next }]
});

tour.addStep("step3", {
    title: "Piyo",
    text: "Step Piyo の説明",
    attachTo: ".piyo bottom",
    buttons: [{ text: "完了", action: tour.complete}]
});

tour.start()
```

```index.html
<!DOCTYPE html>
<meta charset=utf-8>
<title>shepherd.js Test</title>
<script src=dist/main.js defer></script>
<section class=hoge>
    <h1>HOGE</h1>
    <p>hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge.</p>
</section>
<section class=fuga>
    <h1>FUGA</h1>
    <p>fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga. fuga.</p>
</section>
<section class=piyo>
    <h1>PIYO</h1>
    <p>piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo. piyo.</p>
</section>
```

```bash:bash
yarn run webpack
#or
npx webpack 
```

![HOdU6itlsu.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/cab47882-d86f-fa6d-d5d7-e7cd69a9acca.gif)

cssも読み込む必要があったので、`style-loader`, `css-loader`も必要でした。

---

ちなみにダークテーマの方を読み込むと、見た目がこのような感じでした。

```diff
  import Shepherd from "shepherd.js";
- import "shepherd.js/dist/css/shepherd-theme-default.css";
+ import "shepherd.js/dist/css/shepherd-theme-dark.css";
```

<img width="612" alt="Screen Shot 2019-05-12 at 19.03.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/5a9db615-31de-9be6-50fd-31957c67febe.png">


## フロントエンドフレーム

reactやvueでも使えるようなので、うれしいです。

- [angular-shepherd](https://github.com/shipshapecode/angular-shepherd)
- [ember-shepherd](https://github.com/shipshapecode/ember-shepherd)
- [react-shepherd](https://github.com/shipshapecode/react-shepherd)
- [vue-shepherd](https://github.com/shipshapecode/vue-shepherd)

# API

自分が公式を読んで勉強した部分を書いていきます。詳しく知りたい方は公式の方を参考にしてください。

https://shipshapecode.github.io/shepherd/

### ステップのデフォルトオプション

`Tour`のインスタンスを作成するときに`defaultStepOptions`で指定できる。

```js
const tour = new Shepherd.Tour({
  defaultStepOptions: {
    classes: 'shadow-md bg-purple-dark', // 全てのステップでshadow-mdとbg-purple-darkのクラスがつく
    scrollTo: true // 全てのステップでスクロールするかの設定をtrueにする
  }
});
```

### ステップを追加する

```js
tour.addStep('example-step', {
  text: 'This step is attached to the bottom of the <code>.example-css-selector</code> element.', // ステップに表示されるテキスト
  attachTo: '.example-css-selector bottom', // .example-css-selectorの下にステップを表示する
  classes: 'example-step-extra-class', // ステップにクラスを追加する
  buttons: [
    {
      text: 'Next',
      action: tour.next // ステップを次に進める
    },
    {
      text: 'Back', 
      action: tour.back, // ステップを一つ戻す
      classes: 'my-color-gray', // ボタンの色を変えるため、自分でcssを用意して、classを付けてみました
    },
  ]
});
```

<img width="586" alt="Screen Shot 2019-05-12 at 19.23.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/4e2b2c18-8c80-f9e3-b90e-bf038c779469.png">



### ステップにタイトルを追加する

```js
tour.addStep('example-step', {
    title: 'ステップのタイトル',
    text: 'This step is attached to the bottom of the <code>.example-css-selector</code> element.', // ステップに表示されるテキスト
    attachTo: '.example-step-extra-class bottom',
    buttons: [
        {
            text: 'Next',
            action: tour.next
        },
    ]
});
```

<img width="630" alt="Screen Shot 2019-05-12 at 19.31.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/7944c4b4-dc35-729a-c802-6319735b2211.png">

### ステップ終了の`x`ボタンを表示させる

```js
tour.addStep('example-step', {
    text: 'Step Example',
    showCancelLink: true,
    buttons: [
        {
            text: 'Next',
            action: tour.next
        },
    ]
});
```

<img width="630" alt="Screen Shot 2019-05-12 at 19.43.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/36ee058d-9dc9-466f-223c-c19e615377b6.png">

`x`を押したら、ガイドが終了します

### 任意のステップに移動

ボタンに`events`を設定して、そこから任意のステップに移動できます。`click`ではなくても、`mouseover`などでも大丈夫です。

```js
import Shepherd from "shepherd.js";
import "shepherd.js/dist/css/shepherd-theme-dark.css";

let tour = new Shepherd.Tour

tour.addStep("hoge", {
    text: "ステップ名を指定してステップをスキップしたり戻ったりできる",
    buttons: [{
        text: "Hoge", 
        events: {
            click() {
                return Shepherd.activeTour.show('hoge');
            }
        }
    }, {
        text: "Fuga", 
        events: {
            click() {
                return Shepherd.activeTour.show('fuga');
            }
        }
    }, {
        text: "Piyo", 
        events: {
            click() {
                return Shepherd.activeTour.show('piyo');
            }
        }
    }]
});

tour.addStep("hoge", {
    text: "Step Hoge の説明",
    attachTo: ".hoge bottom",
    buttons: [{ text: "次へ", action: tour.next }]
});

tour.addStep("fuga", {
    text: "Step Fuga の説明",
    attachTo: ".fuga bottom",
    buttons: [{ text: "次へ", action: tour.next }]
});

tour.addStep("piyo", {
    text: "Step Piyo の説明",
    attachTo: ".piyo bottom",
    buttons: [{ text: "完了", action: tour.complete}]
});

tour.start()
```

![2ITYTMnJsq.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/5c992143-2272-ab01-6f07-ca93a428e07c.gif)

**注意**

すでに`action`が設定されていた場合は、`click`イベントは動作しません

```js
tour.addStep("hoge", {
    text: "ステップ名を指定してステップをスキップしたり戻ったりできる",
    buttons: [{
        text: "Fuga", 
        action: tour.next, // こちらが実行されます。↓のクリックイベントは実行されません。
        events: {
            click() {
                return Shepherd.activeTour.show('fuga');
            }
        }
    }]
});
```

### ステップ外のイベントからステップを次に進める

`attachTo: "element event" `または`attachTo: {selector: '.hoge', event: 'click'}`

```js
tour.addStep("todo check", {
  text: "チェックをつけることでTodoを完了にできます<br>チェックを付けてみましょう",
  attachTo: ".guide-check right",
  advanceOn: ".guide-check change", // チェックボックスでchageイベントが発生した場合にステップを次に進める
  buttons: [{text: "戻る", action: tour.back}]
});
```

![JBffQD3ayr.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/80ddfea4-bdc3-4295-e4c8-3aeed37db78b.gif)

- 複雑なユーザー操作が必要な場合

`advanceOn`ではつらくなってくる場合はこうすると良いようです。

```js
const myStep = myTour.addStep('my-step', options);

yourApp.on('some-event', () => {
  if (myStep.isOpen()){
    Shepherd.activeTour.next();
  }
});
```

---

- `advanceOn`で指定しているelementにクラスをつけることができる

```diff
  tour.addStep("todo check", {
    text: "チェックをつけることでTodoを完了にできます<br>チェックを付けてみましょう",
    attachTo: ".guide-check right",
    advanceOn: ".guide-check change", // チェックボックスでchageイベントが発生した場合にステップを次に進める
+   highlightClass: "highlight-check", // ステップが表示されている時のみadvanceOnで指定したelementにクラスを付けてくれる
    buttons: [{text: "戻る", action: tour.back}]
  });
```

<img width="1082" alt="Screen Shot 2019-05-12 at 20.54.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/b7dc1ac2-bb66-63f6-2bde-e8ce64091a3b.png">

該当のステップが表示されている時だけ、classを付けてcheckboxにスタイルを適用することができました

### スタイルを変更する

```js
let tour = new Shepherd.Tour({
  defaultStepOptions: {
    classes: 'shepherd-theme-custom'
  }
});
```

<img width="974" alt="Screen Shot 2019-05-12 at 21.06.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/6ede1af7-c6a6-b297-a9a2-975ab5dc9fa3.png">


classを付けてスタイルを変更することができる

### sass変数でテーマを調整できる

こちらの変数を指定すると、自分なりにテーマをカスタマイズできるようです。

- https://github.com/shipshapecode/shepherd/blob/master/src/scss/_variables.scss

変数名と対応するスタイルはドキュメントを確認してください

- https://shipshapecode.github.io/shepherd/#leveraging-sass-variables

---

- webpackでsassを動かして確認

```bash
yarn init -y
yarn add -D shepherd.js webpack webpack-cli css-loader style-loader sass-loader node-sass
```

```webpack.config.js
module.exports = {
    mode: "development",
    module: {
        rules: [{
            test: /\.scss/,
            use: ["style-loader", "css-loader", "sass-loader"]
        }]
    }
};
```

```src/index.js
import Shepherd from "shepherd.js";
import "./my-thema.scss";

let tour = new Shepherd.Tour({
    defaultStepOptions: {
      scrollTo: true
    }
});

tour.addStep("step1", {
    title: "Hoge",
    text: "Step Hoge の説明",
    attachTo: ".hoge bottom",
    buttons: [{ text: "次へ", action: tour.next }]
});

tour.start()
```

```src/my-thema.scss
$shepherd-theme-primary: #9b59b6 !default;
$shepherd-theme-secondary: desaturate(lighten($shepherd-theme-primary, 30), 70) !default;
$shepherd-header-background: #eeeeee !default;
$shepherd-element-border-radius: 0 !default;
$shepherd-button-border-radius: 0 !default;
$use-drop-shadow: true !default;

@import '~shepherd.js/src/scss/base';
```

```index.html
<!DOCTYPE html>
<meta charset=utf-8>
<title>shepherd.js Test</title>
<script src=dist/main.js defer></script>
<section class=hoge>
    <h1>HOGE</h1>
    <p>hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge. hoge.</p>
</section>
```

```bash
yarn run webpack #dist/main.jsが出力
```

<img width="660" alt="Screen Shot 2019-05-12 at 21.30.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142910/511a41cb-cdb8-7468-1673-c0ab7870da20.png">

sassの変数でスタイルを変更することができました

---

最後まで読んでいただいてありがとうございましたm(_ _)m