こんにちわ!本日は現在Reactで開発中のアプリケーションで利用しているMUI(旧 Material-UI)のthemeを拡張してコンポーネントのデザインに一貫性を持たせる方法を公式サイトを参考にしながら簡単にご紹介します。
createThemeでテーマを拡張する
今回はcreateThemeでテーマを拡張して独自のスタイルを定義します。設定できる項目はDefault Themeで設定可能な項目と同じですが、paletteやcomponentsプロパティを弄ることが多いかと思います。下記の例ではcomponents内でButtonBaseコンポーネントのスタイルを弄っています。
import * as React from 'react';
import { createTheme } from '@mui/material/styles';
import Button from '@mui/material/Button';
const theme = createTheme({
components: {
// コンポーネント名
MuiButtonBase: {
defaultProps: {
disableRipple: true, // ボタンの波紋エフェクトを無効化
sx: {
padding: "4px",
},
},
},
},
});
ここで定義したthemeはthemeProviderを用いることで、その範囲内においてスタイルが有効になります。
<ThemeProvider theme={theme}>
<Button>Change default props</Button>
</ThemeProvider>
優先度はインラインが上
上記の例ではdefaultPropsの中でsx propによってpadding 4pxを指定していますが、もしもコンポーネントを利用する側でインラインでsx propを使っている場合、それがpaddingの設定でなくともsx自体がインライン側の内容に上書きされてしまため、上手くスタイル適用が出来ません。
対策として次のようにstyleOverridesを使うことで、確実にスタイルを反映させられます。
const theme = createTheme({
components: {
MuiButton: {
// スタイルをオーバーライド
styleOverrides: {
root: {
padding: '4px',
},
},
// sxで書くこともできる
styleOverrides: {
root: sx({
padding: '4px',
}),
},
},
},
});
styleOverrides内にあるrootはスロットです。スロットとはMUI各コンポーネントを構成しているパーツ(サブコンポーネント)で、アプリケーションを動かして開発者ツールでクラス名を見ればそのコンポーネントがどんなパーツから構成されているか、どのスロットにスタイルを適用すべきかが類推できます。
子要素や疑似要素に対するスタイル適用
コンポーネントの子要素や疑似要素に対するスタイルにも一貫性を持たせる場合は下記の様にcssライクに記述が出来ます。スロット指定だったりクラス名だったりちょっとややこしいですね。
const theme = createTheme({
components: {
MuiAppBar: {
styleOverrides: {
root: {
backgroundColor: 'grey',
'& img': {
padding: '1px',
},
'& .MuiButton-root': {
color: 'black',
fontWeight: 'bold',
'&:hover': {
cursor: 'pointer',
},
},
},
},
},
},
})
受け取るpropsの値によってスタイルを変える
テーマによるスタイルの統一は便利ですが、場合によっては特定のスタイルがすべての箇所ではなく一部のみで使いたい場合がよくあります。そんなときテーマでは強すぎるし、インラインでは何度も同じスタイルを書く羽目になってしまいます。そんな時は下記の様にpropsの値によってスタイル適用処理を分岐させることで解決します。
const theme = createTheme({
components: {
MuiSlider: {
styleOverrides: {
// Sliderコンポーネントのorientationがverticalな時だけスタイルを適用
valueLabel: ({ ownerState, theme }) => ({
...(ownerState.orientation === 'vertical' && {
backgroundColor: 'transparent',
color: theme.palette.grey[500],
}),
}),
},
},
},
});
まとめ
今回は公式サイトの説明を元にMUI v5でcreateThemeを弄ってみました。themeの適用は開発の初期段階である程度形にしておかないと開発者によるUI設計の差異がもろにアプリケーションに反映されてしまうので計画的に進めていきたいですね。