MUIのcreateThemeからd.tsを覗いて中身を理解する


# はじめに

今年の 3 月からフロントエンドエンジニアとして働いています。

エンジニアとして就労する前から、コンポーネントライブラリは、**`MUI`** を使っています。

就労後も、現場で使っているコンポーネントライブラリがたまたま **`MUI`** でした。

つまり、**`MUI`** を触るようになって 1 年が経過していました。（あっという間の 1 年でした。。。）

この 1 年で学んだこと苦戦したことの多くは、**`MUI`** の操作だったんじゃないかと思ったので、備忘録として記事にまとめます。

:::note warn
間違った情報などありましたら、コメントで教えていただけますと幸いです。🙇‍♂️
:::

## MUI とは？

MUI とは、React で利用できる UI コンポーネントライブラリの１つです。

プロジェクトに、ライブラリをインストールするだけで、コンポーネントとして扱えます。

例えば、下のような`Switch`コンポーネントを作りたいシーンがあったとします。

![muisample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/1cded162-aab2-9eac-ba90-371ad0ea0b0e.gif)

MUI を使ったら、下の記述だけで完結できます。

```TypeScript:Switch.tsx
import { Switch } from "@mui/material";

export default function sample() {
  return <Switch />;
}
```

かなり簡単ですよね?

これがコンポーネントライブラリの素晴らしいところです。

## この記事で書きたいこと

MUI を使えばプロジェクトに、コンポーネントを、簡単に作ることができます。

ですが、デフォルトコンポーネントから変化を与えたい場合があると思います。

先ほどの`Switch`コンポーネントで言うと、

- **色を変更したい**
- **トグルのスピードを速さを調節したい**
- **サイズを大きくしたい**

など、デザインのコンポーネントに合わせるためには、いろいろ変更を加える必要があると思います。

こんな場合でも、MUI で用意されている API に適切な props を渡すことで、UI の状態を変えることができます。

ほとんどのコンポーネントには、**`sx`** と言う props が用意されており、CSS in JS を書くことができます。

ですが、私が入った現場では、メンテナンス性、可読性を考慮して **`sx`** を極力使わない方針をとっていました。

**「使えそうな props があるか、どんな感じで探していたのか」** について記録をまとめたいと思います。

### Switch の色を変更したい

Gif のようにトグルの色は、デフォルトが青です。これを変更してみます。

![muisample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/1cded162-aab2-9eac-ba90-371ad0ea0b0e.gif)

MUI で Switch のドキュメントを開きました。

![スクリーンショット 2024-12-29 13.01.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/be6527d4-05e6-4fb3-5eee-937823abe8b9.png)

ドキュメントを開いたら`Color`が用意されてます。すでに用意されている`Color`で問題なければ、color に定義されている props を渡すだけで色を変化できそうです。

color と書き加えたプロパティにマウスをホバーしてみましょう。デフォで、`secondary`、`primary`、`error`、`info`、`success`、`warning`、`default`が割り当てられています。

![スクリーンショット 2024-12-29 13.07.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/ee5a1656-adef-0135-1348-2e1ef8a48004.png)

下のように color に`secondary`を渡してみました。

```TypeScript:Switch.tsx
import { Switch } from "@mui/material";

export default function Sample() {
  return <Switch
  color="secondary"
  />;
}
```

すると、下のように`Switch`コンポーネントの色を簡単に変更できました。めちゃ簡単ですね。

![画面収録 2024-12-29 13.10.55.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/2cd6e29b-4058-8d64-36db-770e664840c6.gif)

### デフォルトで用意されている色以外を割り当てたい場合

おそらく**デフォルトで用意されている色以外を割り当てたい場合**がほとんどだろうと思います。

やり方はいくつかあると思いますが、1 つピックアップして紹介したいと思います。

- **global.tsx で色を変更させる**

#### global.tsx で色を変更させる

Switch コンポーネントの color に、デフォルトで割り当てられている、`secondary`、`primary`、`error`、`info`、`success`、`warning`、`default`の色に上書きする方法です。

これはやったことなかったけど、ずっと試してみたかった方法でした。よくわかんなかったので chatGPT に質問したところ、下のような ThemeProvider を提供してくれました。

```TypeScript:global.tsx
import { createTheme, ThemeProvider as Provider } from "@mui/material/styles";

// カスタムテーマの作成
const theme = createTheme({
  components: {
    MuiSwitch: {
      styleOverrides: {
        // secondaryのスタイルをカスタマイズ
        colorSecondary: {
          "&.Mui-checked": {
            color: "blue", // チェックされた状態のアイコンの色
          },
          "&.Mui-checked + .MuiSwitch-track": {
            backgroundColor: "blue", // チェックされた状態のスライダー背景色
          },
        },
      },
    },
  },
});

interface ThemeType {
  children: React.ReactNode;
}

export default function ThemeProvider({ children }: ThemeType) {
  return <Provider theme={theme}>{children}</Provider>;
}
```

さて、先ほど Switch に渡していた`color="secondary"`の色は変化したのでしょうか？

![画面収録 2024-12-29 13.58.56.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/2cf1c706-14f2-a60a-5c39-2ce3e5427a28.gif)

どうやら無事に`secondary`の色を変更できたようです。

これだとどう言う仕組みで色が変化したのかわからないので、少しコードを折ってみましょう。

まず、下の`createTheme`の`components`を探します。

※`createTheme`をコマンド＋ホバーすることで createTheme に遷移できます。

```TypeScript:global.tsx
const theme = createTheme({
  components: {
    // ↓下を探す
    MuiSwitch: {
      styleOverrides: {
        // secondaryのスタイルをカスタマイズ
        colorSecondary: {
          "&.Mui-checked": {
            color: "blue",
          },
          "&.Mui-checked + .MuiSwitch-track": {
            backgroundColor: "blue",
          },
        },
      },
    },
  },
});
```

`createTheme`の引数として`components`が受け取れることを確認できました。

![スクリーンショット 2024-12-29 14.08.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/d215c5eb-bb06-ca54-b4c5-72c315dda640.png)

では、`components`の中身を確認するために、`CssVarsThemeOptions`に遷移して確認してみましょう。

`CssVarsThemeOptions`の中に`components`があることを確認しました。

![スクリーンショット 2024-12-29 14.16.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/de5914c7-1588-88f5-1415-923b6498b2ab.png)

`components`に渡せるのは`Components`で持ってるものみたいです。`Components`に遷移しましょう。

さて、`components`までやってきました。下の Theme を思い出してください。

```TypeScript:global.tsx
const theme = createTheme({
  components: {
    // ↓下を探す
    MuiSwitch: {
      styleOverrides: {
        // secondaryのスタイルをカスタマイズ
        colorSecondary: {
          "&.Mui-checked": {
            color: "blue",
          },
          "&.Mui-checked + .MuiSwitch-track": {
            backgroundColor: "blue",
          },
        },
      },
    },
  },
});
```

`Components`の中には`MuiSwitch`が存在するはずです。ファイルの中で検索をかけてみてください。

![スクリーンショット 2024-12-29 14.25.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/9fb5e617-9a58-4155-e653-0cdcae1b7e99.png)

`styleOverrides`で渡してる`ComponentsOverrides`を確認します。

`ComponentsOverrides`の中で、`MuiSwitch`を検索かけます

![スクリーンショット 2024-12-29 14.33.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/16fc1f2a-7dca-e76d-70e5-565f708af93b.png)

ありました。`SwitchClassKey`の中身を確認してください。

`colorSecondary: string;`が見つかりました。このプロパティに文字列で渡したら Switch コンポーネントの secondary だけに色を反映させられるようです。（追うのがこんなに長い説明になると思ってなかったです、、、お疲れ様でした。）

![スクリーンショット 2024-12-29 14.34.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/de679e7a-3482-dd61-bff6-7afe56ebdcd0.png)

でも、chatGPT に書いてもらった`colorSecondary`は、色を渡してるだけではありませんね 🤔
`"&.Mui-checked": { color: "blue", },`

これに関しては、Switch コンポーネントの公式ドキュメントを見てみます。

https://mui.com/material-ui/api/switch/

Switch API というページの CSS classes を見てください。

翻訳すると、下のように書いてありました。

> 内部 SwitchBase コンポーネントの checked クラスに適用される状態クラス。

つまり、`checked`が入ってるときの色指定みたいですね。

![スクリーンショット 2024-12-29 14.47.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337943/cadfa1ee-58ca-470c-0d8f-0497008c4454.png)

この場合は、`&クラス名`とすることで、色の指定ができるようでした。

こんな感じで、global.tsx としてコンポーネントの Theme を一元管理できるんです。

でも、毎回グローバルで色を定義するのも面倒ですよね。

下の記事でコンポーネント単位で色を指定する方法を書いてます。

よかったら、見てみてください。🙇‍♂️

https://qiita.com/gtn74/items/34602f0b6aebc82d99ef

## おわりに

デフォで用意されている color を上書きする方法をまとめました。

書きながら`primary`、`secondary`以外の色ってどうやって変更するの？？という疑問が浮かびましたが、記事がかなり長くなりそうだったので、この記事では割愛させてもらいました 🙇‍♂️


私事ですが、今年はエンジニア1年目でかなりバタバタな1年でした。

テックブログも9月から書き始め`Qiita`と`zenn`を合わせて5記事書きました。

来年は、毎月1記事、年間12記事書けるように頑張りたいと思います。

ここまで読んでくれてありがとうございました。🙇‍♂️

良いお年を！🎍