LoginSignup
3
3

Material UIで新しいバリエーションのボタンを作る

Last updated at Posted at 2022-12-07

はじめに

Material UIはReactのコンポーネントライブラリで、Material Designに沿ったコンポーネントを簡単に利用することができます(現在の最新バージョンではMaterial Design 2に対応しています)。この記事ではMaterial UIをカスタマイズして定義されていないバリエーションのボタンを作成します。

テーマの設定

Material UIのテーマの設定はThemeProviderを用いて行うことができます。下の例ではApp配下にそのテーマが適用されます。

<ThemeProvider theme={theme}>
  <App />
</ThemeProvider>

themecreateTheme関数によって作成されます。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は新しいバリエーションを作成するためのキーです。バリューには配列を取り、設定を一つずつ記述します。設定はpropsstyleの二つをとります。styleには反映したいcssを記述します。またこのstylepropsに指定した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コンポーネントをアプリケーション側で作成し直すことや特別なケースだと毎回実装するような運用も考えられます。今回紹介した拡張方法ではどのコンポーネントを使って良いか迷うことや、毎回実装することによる高い工数やミスを避けることができるので利用してみてはいかがでしょうか。

3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3