Nuxt3でVuetify3のテーマを設定する

# はじめに
この記事ではNuxt3でVuetify3のテーマを設定する方法について、公式ドキュメントを参考にして書いています。

https://vuetifyjs.com/en/features/theme/

# 前提条件
Nuxt3、Vuetify３の環境構築は完了している前提で進めていきます。
もしVuetify3の環境構築ができていない場合は、以前書いた記事がありますのでぜひ参考にしてください。

https://qiita.com/MS-0610/items/a16670713de929a5b9b1


# 環境
* Nuxt：3.0.0
* Vue：3.2.45
* Vuetify：3.0.2

# テーマの設定
まずはテーマを設定するために`Vuetify.js`を編集します。
```Vuetify.js
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'

export default defineNuxtPlugin((nuxtApp) => {
  // テーマを定義
  const customTheme = {
    colors: {
      primary: '#2196F3',
      secondary: '#b0bec5',
    }
  }
  const vuetify = createVuetify({
    components,
    theme: {
      themes: {
        customTheme // テーマを設定
      },
    }
  })
  nuxtApp.vueApp.use(vuetify)
})
```
使用する色は下記を参考にすると良いです。

https://vuetifyjs.com/ja/styles/colors/

# テーマを反映
以下の2つの方法について書きます。
* `v-theme-provider`での反映
* コンポーネントのテーマpropでの反映

それでは説明していきます。

## v-theme-providerで反映する方法
`v-theme-provider`タグを使用してテーマを設定します。
公式によると、より大きなまとまりに対してテーマを反映するために使用すると良いみたいです。

https://vuetifyjs.com/en/features/theme/#changing-theme

```vue
<template>
  <v-app>
    <!-- 配下の要素にテーマが反映される -->
    <v-theme-provider theme="customTheme">
      <v-container class="d-flex justify-center align-center h-100">
        <v-card
          class="bg-primary"
          title="customTheme primary"
        >
          <v-card-item class="bg-secondary">
            customTheme secondary
          </v-card-item>
        </v-card>
      </v-container>
    </v-theme-provider>
  </v-app>
</template>
```
![vuetify-theme1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046681/86756138-aa2d-4745-71d6-1f620cfb8cfc.png)

## コンポーネントのテーマpropで反映する方法
下記の`v-card`ようにテーマpropを設定すると、コンポーネント自身とその配下にテーマが反映されます。
```vue
<template>
  <v-app>
    <v-container class="d-flex justify-center align-center h-100">
      <!-- コンポーネント自身とその配下にテーマが反映される -->
      <v-card
        theme="customTheme"
        class="bg-primary"
        title="customTheme primary"
      >
        <v-card-item class="bg-secondary">
          customTheme secondary
        </v-card-item>
      </v-card>
    </v-container>
  </v-app>
</template>
```
![vuetify-theme1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046681/86756138-aa2d-4745-71d6-1f620cfb8cfc.png)

ちなみにドキュメントによるとほとんどのコンポーネントはテーマpropに対応しているそうですが、一部対応していないコンポーネントもあるようです。反映されない場合はコンポーネントが対応している`prop`を確認してみてください。

確認方法ですが、下記のように公式ドキュメントの検索フォームにコンポーネント名を入力して、「コンポーネント名 API」を選択すると対応している`prop`一覧が見れます。
![vuetify-search.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046681/51243880-3f2d-50dc-6d16-9a57d171a179.png)

# その他の設定方法
以下について書いています。
* デフォルトテーマの設定
* 複数テーマの設定
## デフォルトのテーマを設定
下記のようにデフォルトのテーマを設定することもできます。
```Vuetify.js
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'

export default defineNuxtPlugin((nuxtApp) => {
  // テーマを追加
  const customTheme = {
    colors: {
      primary: '#2196F3',
      secondary: '#b0bec5'
    }
  }
  const vuetify = createVuetify({
    components,
    theme: {
      defaultTheme: 'customTheme', // デフォルトテーマ設定
      themes: {
        customTheme
      },
    }
  })
  nuxtApp.vueApp.use(vuetify)
})
```
```vue
<template>
  <v-app>
    <v-container class="d-flex justify-center align-center h-100">
      <v-card
        class="bg-primary"
        title="customTheme primary"
      >
        <v-card-item class="bg-secondary">
          customTheme secondary
        </v-card-item>
      </v-card>
    </v-container>
  </v-app>
</template>
```
上記の`template`タグ内でテーマは設定していませんが、下記のように背景の色が変わっており、デフォルトテーマが反映されていることが確認できます。
![vuetify-theme1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046681/86756138-aa2d-4745-71d6-1f620cfb8cfc.png)


## 複数テーマの設定
複数のテーマを定義し、それぞれ反映させる方法を書いていきます。
方法はとても簡単で、テーマを2つ定義して`themes`に追加し、先ほど説明したように反映するだけです。
```vuetify.js
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'

export default defineNuxtPlugin((nuxtApp) => {
  const customTheme1 = {
    colors: {
      primary: '#2196F3',
      secondary: '#b0bec5'
    }
  }

  const customTheme2 = {
    colors: {
      primary: '#ff9800',
      secondary: '#A1887F',
      error: '#b71c1c',
    }
  }

  const vuetify = createVuetify({
    components,
    theme: {
      themes: {
        customTheme1,
        customTheme2
      },
    }
  })
  nuxtApp.vueApp.use(vuetify)
})
```
```vue
<template>
  <v-app>
    <v-container class="d-flex justify-center align-center h-100">
      <v-card
        theme="customTheme1"
        class="bg-primary"
        title="customTheme primary"
      >
        <v-card-item class="bg-secondary">
          customTheme secondary
        </v-card-item>
      </v-card>
      <v-card
        theme="customTheme2"
        class="bg-primary"
        title="customTheme primary"
      >
        <v-card-item class="bg-secondary">
          customTheme secondary
        </v-card-item>
      </v-card>
    </v-container>
  </v-app>
</template>
```
2種類のテーマが反映されていることが確認できます。
![multiple_themes .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046681/9152d16c-b339-361f-6828-e24599812913.png)


# 最後に
ここまで見ていただきありがとうございました。
Vuetifyって以外と勉強しないといけないこと多いですよね...


# 参考
https://next.vuetifyjs.com/en/features/theme/

https://vuetifyjs.com/ja/styles/colors/