MUIv5のcreateThemeを使って独自の変数にカラーコードを持たす

# はじめに

こんにちは、u-Hoshiです。
普段の業務ではNext.jsやNest.jsを使って開発しています。

# 何を書いたか
今回はReactのUI Toolsの代表的なmuiでオリジナルのキーワードにカラーコードを当てて呼び出せるようにしました。

これによってmuiのデフォルトで準備されている`primary`や`secondary`以外の単語を割り当てられます。


最終ゴールは今回作成する`neutral`がcolorでもsx内でも呼び出せるようにします。
```tsx:page.tsx
<>
  <Button variant="contained" color="neutral">
    neutral
  </Button>

  <Box
    sx={{
      width: 300,
      height: 300,
      backgroundColor: theme.palette.neutral.main,
    }}
  />
</>
```

# なぜ書いたか

元々あるキーワードでもいいのですが、
- わかりづらい
- 数が少ない

などの意見が開発中に上がりました。

恐らくこの問題は自分たちだけでは無いと感じたので今回執筆しました。

# 本題

まずThemeProviderを定義します。MUIのThemeProviderを使用してテーマオブジェクトが子コンポーネント以下で使えるようにします。

`neutral`という変数にピンクに近い色を持たせます。
今回はmainしか使いませんが、後々の開発の中でアプリケーション全体にdarkモード、lightモードを設定した場合は`dark`,`light`に保持されている値を使うことができます。

```tsx:src/ThemeProvider.tsx

import { createTheme, ThemeProvider } from "@mui/material";
import * as React from "react";

export const theme = createTheme({
  palette: {
    neutral: {
      main: "#E01E5A",
      dark: "#621B16",
      light: "#FEECEB",
    },
  },
});
export function Example({ children }: { children: React.ReactNode }) {
  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}

```

## ThemProviderで全体をラップ


次にMUIのThemeProviderを使用してテーマオブジェクトが子コンポーネント以下に提供します。

Next.js13からstableになったAppRouterを使用する場合は`layout.tsx`に記述します。

```tsx:layout.tsx

"use client";

import { ThemeProvider } from "@mui/material";
import { theme } from "@/ThemeProvider/page";

export default function RootLayout({children}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <ThemeProvider theme={theme}>
        <body>{children}</body>
      </ThemeProvider>
    </html>
  );
}

```



 ## MUIのテーマに`neutral`という新しい色のオプションを追加

具体的にはmuiの`Palette`と`PaletteOptions`という２つのインターフェースに`neutral`という新しいカラーオプションを追加します。

ここで設定することでアプリケーション全体で`neutral`が使えるようになります。


```ts:types/createPalette.d.ts
declare module "@mui/material/styles" {
  interface Palette {
    neutral: {
      main: string;
    };
  }
  interface PaletteOptions {
    neutral?: {
      main?: string;
    };
  }
}

```

## MUIのテーマとボタンコンポーネントの型定義を拡張


`PaletteOptions`と`Palette`インターフェースに`neutral`を追加します。

またボタンコンポーネントの`color`プロパティに`neutral`を追加し、Buttonコンポーネントの`color`プロパティに`neutral`を指定することができるようになります。

```ts:themeOption.ts
import { PaletteColorOptions } from "@mui/material";

// PaletteOptions,Palette を拡張して、カラーキーワードを追加
declare module "@mui/material/styles/createPalette" {
  interface PaletteOptions {
    neutral: PaletteColorOptions;
  }
  interface Palette {
    neutral: PaletteColor;
  }
}

// Button の color prop に追加
declare module "@mui/material/Button" {
  interface ButtonPropsColorOverrides {
    neutral: true;
  }
}

```

最後に1番上位コンポーネントのapp直下の`page.tsx`で`neutral`を呼び出して使用します。


```tsx:/app/page.tsx
"use client";
import { theme } from "@/ThemeProvider/page";
import { Box, Button } from "@mui/material";

export default function Home() {
  return (
    <>
      <Button variant="contained" color="neutral">
        neutral
      </Button>

      <Box
        sx={{
          width: 300,
          height: 300,
          backgroundColor: theme.palette.neutral.main,
        }}
      />
    </>
  );
}

```

これで`neutral`で指定した色が正しく表示されていれば成功です。


# 参考文献（なければ不要）

[mui公式palette](https://mui.com/material-ui/customization/palette/)

# 最後に

最後まで読んでいただきありがとうございます！