Vuetify.js 2.2のNavigation drawersコンポーネントについて

# 概要

Navigation drawersコンポーネントの初歩的な使い方のまとめです。

**環境**

* Windows 10 Professional 1909
* Node.js 12.14.1
* Vue.js 2.6.11
* Vuetify.js 2.2.15

**参考**

* [Quick start - Vuetify.js] (https://vuetifyjs.com/en/getting-started/quick-start)
* [Components] (https://vuetifyjs.com/en/components/api-explorer)
* [Styles - Colors] (https://vuetifyjs.com/en/styles/colors)
* [Material Design Icons] (https://cdn.materialdesignicons.com/4.5.95/)

# [Navigation drawers] (https://vuetifyjs.com/en/components/navigation-drawers)

## Props

### VNavigationDrawer

* [VNavigationDrawer] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/components/VNavigationDrawer/VNavigationDrawer.ts)
* [Applicationable] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/mixins/applicationable/index.ts)
* [Positionable] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/mixins/positionable/index.ts)
* [Colorable] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/mixins/colorable/index.ts)
* [Dependent] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/mixins/dependent/index.ts)
* [Overlayable] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/mixins/overlayable/index.ts)
* [SSRBootable] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/mixins/ssr-bootable/index.ts)
* [Themeable] (https://github.com/vuetifyjs/vuetify/blob/v2.2.15/packages/vuetify/src/mixins/themeable/index.ts)

```text
VNavigationDrawer ---- Applicationable ---- Positionable
                  |
                  `--- Colorable
                  `--- Dependent
                  `--- Overlayable
                  `--- SSRBootable
                  `--- Themeable
```

|               |name           |type             |default   |relation                    |src       |
|:--------------|:--------------|:----------------|:---------|:---------------------------|:---------|
|**VNavigationDrawer**|bottom   |boolean          |false     |mobile-break-point          |          |
|               |clipped        |boolean          |false     |                            |          |
|               |disable-resize-watcher|boolean   |false     |                            |          |
|               |disable-route-watcher|boolean    |false     |                            |          |
|               |expand-on-hover|boolean          |false     |mini-variant                |          |
|               |floating       |boolean          |false     |                            |          |
|               |height         |number or string |<font color="blue"><strong>100%</strong></font> |                            | this.app ? '100vh' : '100%'|
|               |mini-variant   |boolean          |false     |                            |          |
|               |mini-variant-width|number or string|<font color="blue"><strong>56</strong></font> |                            |56        |
|               |mobile-break-point|number or string|<font color="blue"><strong>1264</strong></font> |                            |1264      |
|               |permanent      |boolean          |false     |                            |          |
|               |right          |boolean          |false     |                            |          |
|               |src            |string or object |undefined |v-img                       |''        |
|               |stateless      |boolean          |false     |                            |          |
|               |tag            |string           |<font color="blue"><strong>'aside'</strong></font> |                            |this.app ? 'nav' : 'aside'|
|               |temporary      |boolean          |false     |                            |          |
|               |touchless      |boolean          |false     |                            |          |
|               |width          |number or string |<font color="blue"><strong>256</strong></font> |                            |256       |
|               |value          |any              |undefined |                            |          |
|Applicationable|app            |boolean          |false     |                            |          |
|Positionable   |absolute       |boolean          |false     |                            |          |
|               |fixed          |boolean          |false     |                            |          |
|Colorable      |color          |string           |undefined |                            |          |
|Overlayable    |hide-overlay   |boolean          |false     |temporary                   |          |
|               |overlay-color  |string           |undefined |                            |          |
|               |overlay-opacity|number or string |undefined |                            |          |
|Themeable      |dark           |boolean          |false     |                            |null      |
|               |light          |boolean          |false     |                            |null      |

* value : コンポーネントを表示するか非表示にするかを制御します。

## 実装例

ドロワーはVuetifyアプリケーションの一部（v-appコンポーネントに組み込み、v-navigation-drawerコンポーネントの`app`プロパティを指定する）として利用するほかに、アプリケーションとは別に単体で利用することもできます。
以下の実装例の動作結果は、Vuetifyアプリケーションの一部として実装したものになります。

```vue
<template>
  <v-app>
    <v-navigation-drawer app v-model="drawer">
      <v-list-item>
        <v-list-item-title class="title">
          Application
        </v-list-item-title>
        <v-btn icon>
          <v-icon>mdi-chevron-left</v-icon>
        </v-btn>
      </v-list-item>
      <v-divider />
      <v-list nav>
        <v-list-item v-for="menu in menus" :key="menu.title" :to="menu.url">
          <v-list-item-icon>
            <v-icon>{{ menu.icon }}</v-icon>
          </v-list-item-icon>
          <v-list-item-content>
            <v-list-item-title>{{ menu.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>

    <v-app-bar app>
      <!-- アプリケーションバー -->
      <v-app-bar-nav-icon @click.stop="drawer = !drawer" />
    </v-app-bar>

    <v-content>
      <router-view />
    </v-content>

    <v-footer app>
      <!-- フッター -->
    </v-footer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    drawer: false,
    menus: [
      { title: 'Index', icon: 'mdi-web', url: '/' },
      { title: 'Home', icon: 'mdi-home', url: '/home' },
      { title: 'Favorites', icon: 'mdi-heart', url: '/favorites' },
      { title: 'About', icon: 'mdi-information-variant', url: '/about' }
    ]
  })
}
</script>
```

ドロワーの開閉はv-navigation-drawerコンポーネントのv-modelでバインドしたデータで制御します。

### テーマ

**dark**
`dark`プロパティでダークテーマを適用したドロワーです。
![drawer_dark.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/90df35ae-d1e8-83d6-91c7-bf1b9257e6f4.png)

**light**
`light`プロパティでダークテーマを適用したドロワーです。
![drawer_light.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/95fae00a-f90e-c618-a782-bf84fa0bcd85.png)

### カラー

`color`プロパティでドロワーの背景色を指定できます。図はblueを指定したものです。
![drawer_color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/02f69098-2939-dcdd-a959-848f4c64904f.png)

### 常時表示

`permanent`プロパティを指定するとドロワーは画面の表示幅に関係なく常時表示されるようになります。

### 表示幅

`width`プロパティでドロワーの横幅を指定することができます。デフォルトは256pxです。
`height`プロパティでドロワーの縦幅を指定することができます。デフォルトは100%です。

### floating

`floating`プロパティを指定するとドロワーの右側のボーダーを除去（ドロワーを右側に表示する場合は左側のボーダー）します。

**floatingプロパティの指定なし（デフォルト）**
![drawer_floating_off.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/dba4bc63-89c7-12f4-7b38-67f0de3d1424.png)
**floatingプロパティの指定あり**
![drawer_floating_on.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/7eafd9d9-87dd-e0a3-a5bf-29bba9a780b9.png)

### temporary

`temporary`プロパティを指定した場合、ドロワーを開くとアプリケーションの表示領域に被さるように表示され、ドロワー外が半透明の色で覆われます（オーバーレイのエフェクト）。`hide-overlay`プロパティを指定するとオーバーレイのエフェクトは発生しません。
また、ドロワーが表示された状態でドロワー以外の場所をクリックするとドロワーが閉じます。

**temporaryプロパティの指定なし（デフォルト）**
ドロワーを開くとアプリケーションの表示領域がドロワーの分だけ縮みます。
![drawer-large.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/cdced54e-2f56-fa08-2223-c2556e5692ab.gif)

**temporaryプロパティの指定あり**
ドロワーがアプリケーション領域に被さるように表示されドロワー外が半透明の色で覆われます。
![drawer-small.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/2be43385-567c-449a-4f6c-703dce6cdbe5.gif)

### オーバーレイ

`overlay-color`プロパティでオーバーレイの色、`overlay-opacity`プロパティでオーバーレイの透過度を指定します。
図は`overlay-color`にindigoを指定したものです。
![drawer_overlay.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/67c6c8e5-a425-571d-9303-7db68a268ae0.png)

### ドロワーを右側に表示

`right`プロパティを指定するとドロワーは右側に表示されます。

### ドロワーをミニサイズで表示

`mini-variant`プロパティを指定するとドロワーはミニサイズで表示されます。このときの表示幅は`mini-variant-width`プロパティで指定することができます。デフォルトは56pxです。
![drawer_mini.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/379ea857-c28c-7b0d-8a77-b7a24aee48d3.png)

### ホバーで展開

`expand-on-hover`プロパティを指定するとドロワーはミニサイズで表示され（`mini-variant`プロパティの指定に関わらず）、ホバーするとドロワーが展開されます。
![drawer-hover.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/0743110e-f64c-7b17-d2ac-2854a22435ad.gif)

### ドロワーの背景に画像を使用する

`src`プロパティでドロワーの背景画像を指定できます。
後述するimgスロットを使用することで画像にグラデーションなどのエフェクトをかけることもできます。
図はimgスロットでグラデーションをかけたものです。
![drawer_src.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/a3b50232-d370-55b3-e2e3-688b060eec2b.png)

### モバイルデバイス判定

画面の表示幅が`mobile-break-point`プロパティで指定する値（デフォルトは1264）以下になるとモバイルデバイス判定となります。
モバイルデバイスと判定された場合、`temporary`プロパティの指定に関わらず`temporary`プロパティを指定した状態になります。

また`bottom`プロパティを併せて指定するとドロワーは画面下部に表示されます。
![drawer-bottom.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/fc8ac1be-dd5b-ab38-2776-a13448ef6097.gif)

なお、画面下部にナビゲーションメニューを表示する[Bottom navigation] (https://vuetifyjs.com/en/components/bottom-navigation/)というコンポーネントがあります。

### 自動開閉の判定

#### 画面リサイズ時

`disable-resize-watcher`プロパティで画面リサイズ時のドロワー開閉の挙動を決めることができます。
`permanent`を指定しない且つドロワーを表示した状態で、モバイルデバイスと判定されるまで画面の表示幅を狭めると、

**指定しない場合の挙動**

ドロワーが自動的に閉じ`temporary`プロパティを指定した状態と同じになります。（オーバーレイがかかる）

**指定した場合の挙動**

ドロワーは閉じず`temporary`プロパティを指定した状態になります。

#### 画面遷移時

`disable-route-watcher`プロパティで画面遷移時のドロワー開閉の挙動を決めることができます。
`temporary`プロパティを指定し且つドロワーを表示した状態で画面遷移すると、

**指定しない場合の挙動**

遷移後の画面でドロワーを閉じます。

**指定した場合の挙動**

遷移後の画面でもドロワーは閉じません。

### 自動制御を無効にする

`stateless`プロパティを指定すると、自動的に行われていたドロワーの制御が無効になります。
ドロワーの制御をプログラマティックに行いたい時に指定します。

無効になる挙動として

* モバイルデバイス判定が無効になります。
* `template`プロパティを指定したときのドロワー外をクリックしたときのドロワーが閉じる動作が無効になります。

### スロット

#### `prepend`、`append`スロット

ドロワーの先頭、末尾に任意のコンポーネントを追加することができます。

```vue
<template v-slot:prepend>
  <div class="pa-2">
    <v-btn block>prepend</v-btn>
  </div>
</template>

<template v-slot:append>
  <div class="pa-2">
    <v-btn block>Logout</v-btn>
  </div>
</template>
```

![drawer_slot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22772/08f7a8d4-4eaf-38c0-ed6d-225a209c7d93.png)

#### `img`スロット

imgスロットを使うとv-imgコンポーネントで画像にエフェクトをかけることができます。

```vue
<template v-slot:img="{ height, src }">
  <v-img :height="height" :src="src" gradient="to top right, rgba(55,236,186,.7), rgba(25,32,72,.7)"></v-img>
</template>
```