はじめに
こんにちは、u-Hoshiです。
普段の業務ではNext.jsやNest.jsを使って開発しています。
何を書いたか
今回はReactのUI Toolsの代表的なmuiでオリジナルのキーワードにカラーコードを当てて呼び出せるようにしました。
これによってmuiのデフォルトで準備されているprimary
やsecondary
以外の単語を割り当てられます。
最終ゴールは今回作成するneutral
がcolorでもsx内でも呼び出せるようにします。
<>
<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
に保持されている値を使うことができます。
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
に記述します。
"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
という2つのインターフェースにneutral
という新しいカラーオプションを追加します。
ここで設定することでアプリケーション全体でneutral
が使えるようになります。
declare module "@mui/material/styles" {
interface Palette {
neutral: {
main: string;
};
}
interface PaletteOptions {
neutral?: {
main?: string;
};
}
}
MUIのテーマとボタンコンポーネントの型定義を拡張
PaletteOptions
とPalette
インターフェースにneutral
を追加します。
またボタンコンポーネントのcolor
プロパティにneutral
を追加し、Buttonコンポーネントのcolor
プロパティにneutral
を指定することができるようになります。
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
を呼び出して使用します。
"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
で指定した色が正しく表示されていれば成功です。
参考文献(なければ不要)
最後に
最後まで読んでいただきありがとうございます!