はじめに
Material UIはReactのコンポーネントライブラリで、Material Designに沿ったコンポーネントを簡単に利用することができます(現在の最新バージョンではMaterial Design 2に対応しています)。この記事ではMaterial UIをカスタマイズして定義されていないバリエーションのボタンを作成します。
テーマの設定
Material UIのテーマの設定はThemeProvider
を用いて行うことができます。下の例ではApp
配下にそのテーマが適用されます。
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
theme
はcreateTheme
関数によって作成されます。createTheme
の引数に渡すオブジェクトでカスタマイズしたい内容を記述します。Primaryカラーなど色についての設定や、文字の大きさなどTypographyの設定などを行うことができます。今回はMaterial UIが提供しているコンポーネントごとにカスタマイズする設定を利用します。
例えばボタンの横幅を最大にする引数を常にオンにしたいときは以下のようにします。
const theme = createTheme({
components: {
MuiButton: {
defaultProps: {
fullWidth: true,
},
},
},
});
ボタンのfontSizeを20pxにしたいときは以下のようにします。
const theme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
fontSize: '20px',
},
},
},
},
});
目標
Material UIのボタンは引数のvariantを変更することで3種類のボタンを作成することができます。
この記事ではこの三つの他にBootstrapライクなボタンをvariantにbootstarpを指定することで表示できることを目標とします。
BootStrapのボタンを観察する
こちらが今回実装するBootstrapのボタンです。先ほど紹介したMaterial UIのContainedボタンと似ていますが挙動やpaddingも違いますし、微妙な変化ですが色もフォントも異なります。
実装
ボタンのvariant
にbootstrapも指定可能にして、bootstrapを指定した場合にはbootstrapのstyleを当てるようにします。
これらは全てcreateTheme
によって作成できます。variants
は新しいバリエーションを作成するためのキーです。バリューには配列を取り、設定を一つずつ記述します。設定はprops
とstyle
の二つをとります。style
には反映したいcssを記述します。またこのstyle
はprops
に指定したprops
がButtonに設定された時に反映されます。今回は新しくvariant
にbootstrapするので{ variant: "bootstrap" }
にしています。もし、color
にprimaryが指定されているときだけstyle
を反映したいときは{ variant: "bootstrap", color: "primary" }
にすることでできます。
const theme = createTheme({
components: {
MuiButton: {
variants: [
{
props: { variant: "bootstrap" },
style: {
color: "white",
boxShadow: "none",
textTransform: "none",
fontSize: 16,
padding: "6px 12px",
border: "1px solid",
lineHeight: 1.5,
backgroundColor: "#0063cc",
borderColor: "#0063cc",
fontFamily: [
"-apple-system",
"BlinkMacSystemFont",
'"Segoe UI"',
"Roboto",
'"Helvetica Neue"',
"Arial",
"sans-serif",
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"'
].join(","),
"&:hover": {
backgroundColor: "#0069d9",
borderColor: "#0062cc",
boxShadow: "none"
},
"&:active": {
boxShadow: "none",
backgroundColor: "#0062cc",
borderColor: "#005cbf"
},
"&:focus": {
boxShadow: "0 0 0 0.2rem rgba(0,123,255,.5)"
}
}
}
]
}
}
});
typescriptを利用の方はここで型エラーが出るはずです。なぜならMaterial UIのButtonの実装を見ると、Buttonの型が以下の様になっているからです。
export interface ButtonPropsVariantOverrides {}
{
variant?: OverridableStringUnion<
'text' | 'outlined' | 'contained',
ButtonPropsVariantOverrides
>;
}
ButtonPropsVariantOverrides
は空ですから'text'
と'outlined'
、'contained'
しかとれないようになっています。これではvariant
に'bootstrap'
を与えても型が解決されずエラーになってしまいます。Material UIでは拡張されることに備えてButtonPropsVariantOverrides
を用意しています。これを下のようにthemeを定義するタイミングで拡張してあげれば型のエラーが出なくなるようにできます。
declare module "@mui/material/Button" {
interface ButtonPropsVariantOverrides {
bootstrap: true;
}
}
これらの設定を全て完了させると、以下のようにMaterial UIでBootstrapのボタンを作ることができます。クリックすると波紋が広がる機能はBootstrapにはないのでdisableRipple
をpropsに与えています。
さいごに
アプリケーションの開発では、Material UIのコンポーネントに実装されているバリエーションでは足りないケースが出てくる時があります。そうなった時にButtonコンポーネントをアプリケーション側で作成し直すことや特別なケースだと毎回実装するような運用も考えられます。今回紹介した拡張方法ではどのコンポーネントを使って良いか迷うことや、毎回実装することによる高い工数やミスを避けることができるので利用してみてはいかがでしょうか。