🦔

material-uiのテーマとコンポーネントのカスタマイズについて

2021/08/12に公開

最近material-uiを触り始めたので、表題の件について自分の見解を述べていきます。

material-uiとは?

materiul-uiとは、マテリアルデザインを簡単に実現することができるデザインライブラリです。
Bootstrapとは違い、Reactでしか使えないはず...
VueでいえばVuetifyみたいな感じですよねたぶん。

テーマとは

まず、「テーマってなんぞや?」となる方は下記の公式ページをご覧ください。
https://material-ui.com/customization/default-theme/

上記のように、デフォルトでテーマというものがmaterial-uiには存在します。
で、サンプルのコードとか見ると好き勝手にこのthemeから値を持ってきたりしています。

toolbar: {
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'flex-end',
        padding: theme.spacing(0, 1),
        ...theme.mixins.toolbar,
    }

まあこんな感じですね。
まず、テーマを使っているのは、paddingのところですね。
こちらは関数で、引数の値の8倍の数値を返り値として戻してくれるというものです。
つまり、上記をCSSで言えば

padding: 0px 8px;

となるわけです。
で、次の「...theme.mixins.toolbar」というのはスプレッド演算子によってオブジェクトを展開しています。
なので、デフォルトテーマで定義されているtoolbarのcssプロパティを継承している、ということですね。

テーマのカスタマイズ

とまあ、こんな感じで使われているテーマなのですが、まず最初に意識するのは色だと思います(思い込み)のでデフォルトテーマをカスタマイズして、色を変えてみましょう。
materiul-uiには「パレット」という概念があり、こちらもデフォルトで色が定義されています。
https://material-ui.com/customization/palette/

普通に使うなら、下記のような感じで使えます。

toolbar: {
        color: theme.palette.primary.main,
    }

で、colorプロパティが使えるコンポーネントなら下記のように使います。

<Typography color={'primary'}></Typography>

さて、デフォルトで指定されている色を変えたいなーて時があると思います。

こういう場合は、createThemeとThemeProviderを使います。

import { createTheme, ThemeProvider } from '@material-ui/core/styles';

const testTheme = createTheme({
  palette: {
    secondary: {
      main: '#000',
    },
  },
});

const App = () => {
  return (
    <ThemeProvider theme={testTheme}>
      <Typography color={'secondary'}></Typography>
    </ThemeProvider>
  );
}

プロバイダーという概念はReactを触ったことがある方なら馴染み深いですよね。
ThemeProviderにthemeプロパティとして、createThemeで作成したThemeオブジェクトを渡すことによって、プロバイダー内のコンポーネントには渡したオブジェクトを内容でデフォルトのパレットの色をオーバーライドすることができるようになります。
もちろん、その他のデフォルトテーマの値も変えることができるので、その辺はプロジェクトと相談して調整ですね。

コンポーネントのカスタマイズ

コンポーネントめちゃくちゃありますよね。
でも、「なんかこの挙動気に食わないな...」とか「色変えたいんだけどどうすりゃいいの?」とかあると思います。

で、コンポーネントのカスタマイズには方法が二つあると認識しています。

  1. useStylesを使う方法
  2. クラスの上書き

この二つを見ていきたいと思います。

useStylesを使ってコンポーネントをカスタマイズ

基本的にはコンポーネントのAPIを見ることをお勧めします。
今回例に挙げるのは「Tab」コンポーネントです。
https://material-ui.com/api/tab/
ここで見ていくのは、上記のドキュメントの中でも「CSS」の部分ですね。

import { withStyles } from '@material-ui/core/styles';
import {Tab} from '@material-ui/core';

const tabStyles = () => ({
    root: {
        color: "#bdc0c4",
        "&:hover": {
            color: "#ffffff",
            opacity: 1
        },
        "&:selected": {
            color: "#1890ff",
        },
        textTransform: "initial"
    },
    selected: {}
});

const StyledTab = withStyles(tabStyles)(Tab)

const App = () => {
	return(
	<Tabs value={tabState} aria-label="simple tabs example">
	  <StyledTab label="Tab 1" />
	  <StyledTab label="Tab 2" />
	  <StyledTab label="Tab 3" />
        </Tabs>
	)
}

CSSの中に、rootとかselectedとかありますよね。
これをテーマをオーバーライドするときのように、好きなプロパティを好きな値で定義します。
で、withStylesを使って、作成したスタイルをコンポーネントに反映させて、新しい独自のコンポーネントを作成します。
変わったのはスタイルだけなので、挙動は普通のTabコンポーネントと同じように利用することができます。

クラスの上書きを使ってコンポーネントをカスタマイズ

まあほぼ上記のuseStylesとやってることは同じです。
例を出します。

import {Typography} from '@material-ui/core';
const useStyles = makeStyles((theme) => ({
 h1: {
        fontSize: '100px'
    }
}))

const App = () => {
const classes = useStyles();

return(
  <Typography variant={'h1'} classes={{ h1: classes.h1 }}>タイポグラフィ</Typography>
)
}

今度はTypographyコンポーネントにしてみました。
例に倣って、こちらもコンポーネントAPIをみてもらうとわかるのですが、propsとしてvariantというプロパティがありますよね。
で、このh1という指定の場合に、フォントサイズをちょっと上げたいなーって思った時とかの例です。
まず、重要なのは「variant={'h1'} 」を指定することです。
これで、h1のプロパティを使うのね、ということを伝えることができます。
で、そのh1のプロパティのフォントサイズだけちょっと変えるよーっていうことで、コンポーネントの「classes」にフォントサイズだけを変えるCSSプロパティを指定しています。

これで、部分的にコンポーネントのスタイルを変えることができました。

まとめ

テーマとコンポーネントのカスタマイズについて話してみました。
テーマの変更はまあおそらくレイアウト単位とかでやると思いますが、コンポーネントに関しては、そこまで大袈裟に修正しなくても良さそうなものはクラスで上書き、そうでないものはuseStylesを使ってコンポーネントを切り出す、という感じで良いのかなと思いました。
ご意見、ご感想、ご相談、お待ちしております...

Discussion