LoginSignup
8
7

More than 5 years have passed since last update.

Material UIでProps渡しで色指定できるCustomButtonを作る

Posted at

Material UIのボタンにはデフォルトで以下の様なレパートリーがあるのだけれど
img_20190503.png
デフォルトのままではBootstrapと比べて色数が少なく
Material UIにはせっかく豊富なカラーパレットが用意されているのでこれをprops渡しで色指定できるボタンを何とか作れないかと試行錯誤

公式ドキュメントにはCustomized buttonsの作り方が説明されているけれども固定色の為なんとか色指定できる汎用的なコンポーネントにしようと試したところコンパイルエラーの嵐

これを

const ColorButton = withStyles(theme => ({
  root: {
    color: theme.palette.getContrastText(purple[500]),
    backgroundColor: purple[500],
    '&:hover': {
      backgroundColor: purple[700],
    },
  },
}))(Button);

こうしようとしたらNGだった

const ColorButton = (props)=> withStyles(theme => ({
  root: {
    color: theme.palette.getContrastText(props.themeColor[500]),
    backgroundColor: props.themeColor[500],
    '&:hover': {
      backgroundColor: props.themeColor[700],
    },
  },
}))(Button);

色々書き換えて試してみたがうまくいかず

別のテーマ指定の方法を書き換えてみたところ

const theme = createMuiTheme({
  palette: {
    primary: green,
  },
});

function CustomizedButtons() {
  return (
    <>
      <ThemeProvider theme={theme}>
        <Button variant="contained" color="primary">
          Theme Provider
        </Button>
      </ThemeProvider>
    </>
  );
}

const CustomButton = (props) => (
  <ThemeProvider theme={createMuiTheme({palette:{primary:props.themeColor}})}>
    <Button variant="contained" color="primary" className={props.className}>
      {props.label}
    </Button>
  </ThemeProvider>
)

function App() {
  return (
    <>
      <CustomButton label="Hello" themeColor={purple} />
    </>
  );
}

上手くいった
img_20190503(1).png

かに見えたけど

違う色を並べてみたところ

function App() {
  return (
    <>
      <CustomButton label="Hello" themeColor={purple} />
      <CustomButton label="Hello" themeColor={green} />
    </>
  );
}

KONOZAMA☆
img_20190503(2).png

もう一度withStylesでやる路線に
前の書き換え試行錯誤で以下は

const ColorButton = withStyles(theme => ({
  root: {
    color: theme.palette.getContrastText(purple[500]),
    backgroundColor: purple[500],
    '&:hover': {
      backgroundColor: purple[700],
    },
  },
}))(Button);

このように書き換えられるところまでは分かり
withStyles(customTheme)の戻り値はコンポーネントを引数とする関数
withStyles(customTheme)(Button)の戻り値はコンポーネントそのものという事
何かあと一歩足りない

  const customTheme = theme => ({
    root: {
      color: theme.palette.getContrastText(purple[500]),
      backgroundColor: purple[500],
      '&:hover': {
        backgroundColor: purple[700],
      },
    },
  })
  const CustomButton = withStyles(customTheme)(Button)

もう一度withStylesにpropsを渡す方法がないかQiitaで探してたら

…あった
Material-UIのwithStylesで指定するstylesCreatorの中で親からpropsとして受け取った値を動的に適応させるHOC

あるじゃないか

> const withStylesProps = styles => Component => props => {
>   const Comp = withStyles(styles(props))(Component);
>   return <Comp {...props} />;
> };

jsxってこう書くのか…

というわけで欲しかった方法はこんな感じでした(見易さのためmargin関連省略)

import React from 'react';
import Button from '@material-ui/core/Button';
import { withStyles } from '@material-ui/core/styles';
import { purple, green, red, blue } from '@material-ui/core/colors';

const CustomButton = (props) => {
  const customTheme = theme => ({
    root: {
      color: theme.palette.getContrastText(props.themeColor[500]),
      backgroundColor: props.themeColor[500],
      '&:hover': {
        backgroundColor: props.themeColor[700],
      },
    },
  })
  const ComponentName = withStyles(customTheme)(Button)
  return <ComponentName {...props} />
}

function App() {
  return (
    <>
      <CustomButton themeColor={green}>Hello</CustomButton>
      <CustomButton themeColor={purple}>Hello</CustomButton>
      <CustomButton themeColor={red}>Hello</CustomButton>
      <CustomButton themeColor={blue}>Hello</CustomButton>
    </>
  );
}

export default App;

見た目はこんな感じ
img_20190503(3).png

8
7
0

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
8
7