ReactのMaterial-UIでのダークテーマ対応(システムのテーマをリアルタイムで反映しつつprimary/secondaryの対応もする)
やりたいこと
システムの設定でテーマを変更をリアルタイムで反映したい。
primary/secondaryの色もlight/darkテーマ共に見やすくしたい。
@material-ui/coreは4.11.4を使っている。
デモ
https://gyazo.com/885b59feaccc8b6300c3bfa47ec6f91a
上記はFirefox。ChromeとSafariでも試して同じように動作することを確認した。
やりかた
以下で実現した。説明はこのコードの下にある。
code:tsx
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {useMediaQuery} from '@material-ui/core';
import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
import CssBaseline from '@material-ui/core/CssBaseline';
import {blue, pink} from "@material-ui/core/colors";
function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const theme = React.useMemo(() => {
const primary = blue;
const secondary = pink;
const darkPrimary = {
};
const darkSecondary = {
};
return createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : undefined,
primary: prefersDarkMode ? darkPrimary : undefined,
secondary: prefersDarkMode ? darkSecondary : undefined,
},
})
return (
<>
<ThemeProvider theme={theme}>
<CssBaseline/>
{/* ここに好きなコンポーネントを入れる */}
</ThemeProvider>
</>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
システムのテーマ
まずシステム設定のテーマ状態を検出しつつ変更後に反映するためにはuseMediaQuery('(prefers-color-scheme: dark)')を使えば良い。
primary/secondaryの問題と解決
上記でdarkPrimaryとdarkSecondaryを定義して使っている。これは現在のMaterial-UIの場合、palette.type: 'dark'にしてもprimaryとsecondaryの色がdarkの時に見やすい色にはならない問題があるため。 The primary and secondary colors are identical between the light and dark theme.
primary/secondaryのカスタマイズ
primaryとsecondaryの色をカスタマイズするには、const primary = blue;とconst secondary = pink;をindigoなどにすれば良い。"@material-ui/core/colors"を辿ればどんな色が使えるかわかる。
デモのコード
最初のデモでは以下の<MyComponent />を定義して、{/* ここに好きなコンポーネントを入れる */}に入れてデモしている。
code:tsx
import {FormControl, FormControlLabel, FormLabel, Paper, Radio, RadioGroup,} from '@material-ui/core';
function MyComponent() {
return (
<Paper style={{margin: '1rem', padding: '1rem'}}>
<FormControl component="fieldset">
<FormLabel component="legend">Gender</FormLabel>
<RadioGroup aria-label="gender" name="gender1" >
<FormControlLabel value="female" control={<Radio />} label="Female" />
<FormControlLabel value="male" control={<Radio />} label="Male" />
<FormControlLabel value="other" control={<Radio />} label="Other" />
<FormControlLabel value="disabled" disabled control={<Radio />} label="(Disabled option)" />
</RadioGroup>
</FormControl>
</Paper>
)
}