【Material UI】カラーパレット・ダークテーマ実装の覚書
この記事は、Gajeroll Advent Calendar 2022 の 19 日目の記事です。
はじめに
みんな大好き、Material UI。この記事では、Material UI を使う際のテーマ設定の方法を紹介します。
Material UI とは
Material UI は Material Design を実装したもの
Material UI is a library of React UI components that implements Google's Material Design.
Google の Material Design は 2014 年に初めてリリースされ、2021 年、最新の Material Design 3 が発表されました。Material UI v5 では、1 世代前の Material Design 2 が実装されています。
2021 年に名称が変更
Material UI?Material Design?MUI?似たような名詞が複数ありますが、現在は以下のようになっています。
Starting today we are evolving our brand identity to clarifying the difference between our company and our products.
- Material UI: the organization is now called MUI.
- Material UI: the set of foundational MIT React components is now called MUI Core.
- Material UI: the Material Design components developed by MUI. Also, we ditched the hyphen!
- Material UI X: the set of advanced React components is now called MUI X. Our previous name was no longer serving our areas of focus. We have grown our product offering. We needed a new identity to match our increased scope.
引用: Material UI is now MUI! - MUI
Material Design は先述の通り、Google のデザインシステムです。
カラーパレットをカスタマイズする
現行の Material UI は M2 が実装されているため、デフォルトのカラーシステムも M2 に準拠します。カラーパレットをカスタマイズするためには、createTheme
関数と ThemeProvider
(コンポーネント)を使います。
createTheme
関数
createTheme
関数は、引数として options
をとり、その options
に基づいて、テーマを生成します。戻り値を後述の ThemeProvider
の prop として渡します。
ThemeProvider
prop としてテーマをとり、ラップしているコンポーネントにテーマを適用します。App.jsx
等のルートに近いところで使うイメージです。
import * as React from "react";
import { red } from "@mui/material/colors";
import { ThemeProvider, createTheme } from "@mui/material/styles";
const theme = createTheme({
palette: {
primary: {
main: red[500],
},
},
});
function App() {
return <ThemeProvider theme={theme}>...</ThemeProvider>;
}
ちなみに、Material Design 2 に準拠するカラーテーマを作りたい場合は、こちらの公式のツールが利用できます。
ダークモードに対応する
アプリケーションのテーマをダークテーマにするには、 createTheme
の palette
の mode
を dark
に設定すればよいです。
import { ThemeProvider, createTheme } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
const darkTheme = createTheme({
palette: {
mode: "dark",
},
});
function App() {
return (
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<main>This app is using the dark mode</main>
</ThemeProvider>
);
}
export default App;
ライト・ダークでカラーパレットを変える
前項の方法では、常にダークテーマで表示されてしまいます。ライト・ダークのテーマに応じて異なるカラーパレットを使うには、以下のように、モードを引数にとってオプションのオブジェクトを返す関数を用意します。
const getDesignTokens = (mode: PaletteMode) => ({
palette: {
mode,
...(mode === "light"
? {
// palette values for light mode
primary: amber,
secondary: amber[200],
}
: {
// palette values for dark mode
primary: deepOrange,
secondary: deepOrange[700],
}),
},
});
ライト・ダークを切り替え
ライト・ダークでテーマの切り替えは、カラーパレットの mode
を変更することで実現できます。React のフックを使えば容易に実装できるでしょう。以下は、公式ドキュメント内のコード例を引用しています。
import * as React from "react";
import IconButton from "@mui/material/IconButton";
import Box from "@mui/material/Box";
import { useTheme, ThemeProvider, createTheme } from "@mui/material/styles";
import Brightness4Icon from "@mui/icons-material/Brightness4";
import Brightness7Icon from "@mui/icons-material/Brightness7";
const ColorModeContext = React.createContext({ toggleColorMode: () => {} });
function MyApp() {
const theme = useTheme();
const colorMode = React.useContext(ColorModeContext);
return (
<Box
sx={{
display: "flex",
width: "100%",
alignItems: "center",
justifyContent: "center",
bgcolor: "background.default",
color: "text.primary",
borderRadius: 1,
p: 3,
}}
>
{theme.palette.mode} mode
<IconButton
sx={{ ml: 1 }}
onClick={colorMode.toggleColorMode}
color="inherit"
>
{theme.palette.mode === "dark" ? (
<Brightness7Icon />
) : (
<Brightness4Icon />
)}
</IconButton>
</Box>
);
}
export default function ToggleColorMode() {
const [mode, setMode] = React.useState("light");
const colorMode is React.useMemo(
() => ({
toggleColorMode: () => {
setMode((prevMode) => (prevMode === "light" ? "dark" : "light"));
},
}),
[]
);
const theme is React.useMemo(
() =>
createTheme({
palette: {
mode,
},
}),
[mode]
);
return (
<ColorModeContext.Provider value={colorMode}>
<ThemeProvider theme={theme}>
<MyApp />
</ThemeProvider>
</ColorModeContext.Provider>
);
}
デバイスのテーマ設定を使う
デフォルトのカラーテーマを OS のテーマに合わせるには、useMediaQuery
という API を使います。
useMediaQuery
は引数で渡した CSS メディアクエリが正しいかどうかの真偽値を返します。
この関数の引数として、ユーザーのシステムのカラーテーマがダークテーマであるという旨の (prefers-color-scheme: dark)')
を指定すれば、ダークモードの場合には true
、そうでない場合には false
を返します。
import * as React from "react";
import useMediaQuery from "@mui/material/useMediaQuery";
import { createTheme, ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
function App() {
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const theme = React.useMemo(
() =>
createTheme({
palette: {
mode: prefersDarkMode ? "dark" : "light",
},
}),
[prefersDarkMode]
);
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Routes />
</ThemeProvider>
);
}
おわりに
最後までご覧いただきありがとうございます。 PC ロールでは、テクノロジーに関する情報をまとめて発信しています。 また、おすすめのガジェットについて幅広く紹介していく、ガジェロールもあります。 ガジェットやソフトを使うエンジニア・クリエイターはぜひご覧ください。