具有类似<button>外观的Material-UI <radio>

时间:2018-08-01 05:00:35

标签: reactjs material-ui

仅使用 Material-UI,是否可以使用<Radio />类型的外观来设置<Button />对象的样式?如果没有,最简单的选择是什么?

花了几天的时间阅读文档和进行实验之后,我觉得没有什么比这更接近解决方案了。感谢任何可以提供一些指导的人。

这是我的出发点(没有进行%an实验),以防有人使用我正在使用的东西:

<Button />

更新:

对于任何好奇的人,当我问这个问题时,Material-UI都没有快速解决此问题的方法,因此最终不得不为按钮创建自己的CSS。如果您需要帮助,这就是我的实现方式:

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import RadioGroup from '@material-ui/core/RadioGroup';
import Radio from '@material-ui/core/Radio';
import Button from '@material-ui/core/Button';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControl from '@material-ui/core/FormControl';

const styles = theme => ({
  textField: {
    marginLeft: theme.spacing.unit,
    marginRight: theme.spacing.unit,
    width: '100%',
  },
  formControl: {
    display: 'flex',
    flexBasis: '100%',
    alignItems: 'center',
  }
});

class QRadios extends React.PureComponent {
  constructor(props, context) {
    super(props, context);
    this.state = {
      value: this.props.value,
    };
  }

  handleChange = event => {
    this.setState({
      value: event.target.value,
    },
      this.props.onChange(event)); 
  };

  render() {
    const { classes } = this.props;

    return (
      <FormControl component="ul" className={classes.formControl} required>
        <RadioGroup
          row={true}

          id={this.props.id}
          name={this.props.name}

          value={this.state.value}
          onChange={this.handleChange}
        >
          <FormControlLabel
            htmlFor={this.props.id}
            value="good"
            control={<Radio />} 
          />
          <FormControlLabel
            htmlFor={this.props.id}
            value="okay"
            control={<Radio />}
          />
          <FormControlLabel
            htmlFor={this.props.id}
            value="bad"
            control={<Radio />} 
          />
          <FormControlLabel
            htmlFor={this.props.id}
            value="na"
            control={<Radio />} 
          />
        </RadioGroup>
      </FormControl>
    );
  }
}

QRadios.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(QRadios);

用法...

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import green from '@material-ui/core/colors/green';
import yellow from '@material-ui/core/colors/yellow';
import red from '@material-ui/core/colors/red';
import grey from '@material-ui/core/colors/grey';
import RadioGroup from '@material-ui/core/RadioGroup';
import Radio from '@material-ui/core/Radio';
import FormControl from '@material-ui/core/FormControl';
import InputLabel from '@material-ui/core/InputLabel';

const styles = theme => ({
  formControl: {
    display: 'flex',
    flexBasis: '100%',
    alignItems: 'stretch',
    margin: theme.spacing.unit * 3 / 2
  },
  formGroup: {
    alignItems: 'stretch',
    justifyContent: 'space-around',
    flexWrap: 'nowrap'
  },
  radioFlex: {
    flex: '1 1 auto',
    margin: '0 5px'
  },
  greenButtonRoot: {
    backgroundColor: '#00000004',
    borderRadius: 5,
    border: '1px solid',
    color: green.A700,
    fontFamily: 'monospace',
    fontSize: '180%',
    height: 32,
    '&$checked': {
      backgroundColor: green.A700,
      color: 'white'
    },
    '&:not($checked):hover': {
      backgroundColor: green['50']
    },
    transition: 'background-color 250ms'
  },
  yellowButtonRoot: {
    backgroundColor: '#00000004',
    borderRadius: 5,
    border: '1px solid',
    color: yellow['700'],
    fontFamily: 'monospace',
    fontSize: '200%',
    height: 32,
    '&$checked': {
      backgroundColor: yellow.A700,
      color: 'white'
    },
    '&:not($checked):hover': {
      backgroundColor: yellow['100']
    },
    transition: 'background-color 250ms'
  },
  redButtonRoot: {
    backgroundColor: '#00000004',
    borderRadius: 5,
    border: '1px solid',
    color: red.A700,
    fontFamily: 'monospace',
    fontSize: '160%',
    height: 32,
    '&$checked': {
      backgroundColor: red.A700,
      color: 'white'
    },
    '&:not($checked):hover': {
      backgroundColor: red['50']
    },
    transition: 'background-color 250ms'
  },
  greyButtonRoot: {
    backgroundColor: '#00000004',
    borderRadius: 5,
    border: '1px solid',
    color: grey['700'],
    fontFamily: 'monospace',
    fontSize: '180%',
    height: 32,
    '&$checked': {
      backgroundColor: grey['700'],
      color: 'white'
    },
    '&:not($checked):hover': {
      backgroundColor: grey['200']
    },
    transition: 'background-color 250ms'
  },
  disabled: {
    backgroundColor: '#00000004'
  },
  checked: {}
});

function QRadios(props) {
  const {
    classes,
    error,
    required,
    id,
    label,
    name,
    binaryChoice,
    value,
    onChange,
    onBlur
  } = props;

  return (
    <FormControl className={classes.formControl} required={required}>
      <InputLabel
        error={error}
        required={required}
        shrink
        style={{
          position: 'relative',
          marginBottom: '10px'
        }}
      >
        {label}
      </InputLabel>
      <RadioGroup
        className={classes.formGroup}
        row

        id={id}
        name={name}

        value={value}
        onChange={onChange}
        onBlur={onBlur}
      >
        <Radio
          htmlFor={id}
          className={classes.radioFlex}

          value="good"
          classes={{
            root: classes.greenButtonRoot,
            checked: classes.checked
          }}
          icon="〇"
          checkedIcon="〇"
        />
        <Radio
          htmlFor={id}
          className={classes.radioFlex}

          value="okay"
          classes={{
            root: classes.yellowButtonRoot,
            checked: classes.checked,
            disabled: classes.disabled
          }}
          icon="△"
          checkedIcon="△"
          disabled={binaryChoice}
        />
        <Radio
          htmlFor={id}
          className={classes.radioFlex}

          value="bad"
          classes={{
            root: classes.redButtonRoot,
            checked: classes.checked
          }}
          icon="✕"
          checkedIcon="✕"
        />
        <Radio
          htmlFor={id}
          className={classes.radioFlex}

          value="na"
          classes={{
            root: classes.greyButtonRoot,
            checked: classes.checked
          }}
          icon="-"
          checkedIcon="-"
        />
      </RadioGroup>
    </FormControl>
  );
}

QRadios.propTypes = {
  classes: PropTypes.object.isRequired,
  required: PropTypes.bool,
  error: PropTypes.bool,
  id: PropTypes.string.isRequired,
  label: PropTypes.string.isRequired,
  name: PropTypes.string.isRequired,
  binaryChoice: PropTypes.bool,
  value: PropTypes.string,
  onChange: PropTypes.func.isRequired,
  onBlur: PropTypes.func
};

QRadios.defaultProps = {
  required: false,
  binaryChoice: false,
  error: false,
  onBlur: null,
  value: ''
};

export default withStyles(styles)(QRadios);

2 个答案:

答案 0 :(得分:1)

这是您可以使单选按钮具有类似按钮的功能,我为此创建了一支笔,请检查https://codepen.io/praveen-rao-chavan/pen/JBpgLX

<section>
  <h1>Simple material design CSS only radio button example</h1>
  <div>
    <ul  class="donate-now">
    <li class="md-radio">
      <input id="1" type="radio" name="g" checked>
      <label for="1">Option 1</label>
    </li>
    <li class="md-radio">
      <input id="2" type="radio" name="g">
      <label for="2">Option 2</label>
    </li>
      </ul>
  </div>
</section>

CSS

@import url(https://fonts.googleapis.com/css?family=Roboto);

$md-radio-checked-color: rgb(51, 122, 183);
$md-radio-border-color: rgba(0, 0, 0, 0.54);
$md-radio-size: 20px;
$md-radio-checked-size: 10px; 
$md-radio-ripple-size: 15px;

@keyframes ripple {
  0% {
    box-shadow: 0px 0px 0px 1px rgba(0, 0, 0, 0.0);
  }
  50% { 
    box-shadow: 0px 0px 0px $md-radio-ripple-size rgba(0, 0, 0, 0.1);
  }
  100% {
    box-shadow: 0px 0px 0px $md-radio-ripple-size rgba(0, 0, 0, 0);
  }
}

.md-radio {
    margin: 16px 0;

    &.md-radio-inline {
        display: inline-block;
    }

    input[type="radio"] {
        display: none;
        &:checked + label:before {
            --border-color: $md-radio-checked-color;
            --animation: ripple 0.2s linear forwards;   
        }
        &:checked + label:after {
            --transform: scale(1);
        }
    }

    label {
        display: inline-block;
        height:$md-radio-size;
        position: relative;
        padding: 0 ($md-radio-size + 10px);
        margin-bottom: 0;
        cursor: pointer;
        vertical-align: bottom;
        &:before, &:after {
            position: absolute;            
            content: '';  
            border-radius: 50%;
            transition: all .3s ease;
            transition-property: transform, border-color;
        }
        &:before {
            left: 0;
            top: 0;
            width: $md-radio-size;
            height: $md-radio-size;
            border: 2px solid $md-radio-border-color;
        }
        &:after {
            top: $md-radio-size / 2 - $md-radio-checked-size / 2;
            left: $md-radio-size / 2 - $md-radio-checked-size / 2;
            width:$md-radio-checked-size;
            height:$md-radio-checked-size;
            transform: scale(0);
            background:$md-radio-checked-color;
        }
    }
}



// *************************************

// *************************************
*, *:before, *:after {
  box-sizing: border-box;
}

body {
  background:#f0f0f0;
  position: absolute;
  width:100%;
  padding:0;
  margin:0;
  font-family: "Roboto", sans-serif;
  color: #333;
}

section {
  background:white;
  margin:0 auto;
  padding: 4em;
  max-width: 800px;
  h1 {
    margin: 0 0 2em;
  }
}



.donate-now {
     list-style-type:none;
     margin:25px 0 0 0;
     padding:0;
}

.donate-now li {
     float:left;
     margin:0 5px 0 0;
    width:100px;
    height:40px;
    position:relative;
}

.donate-now label, .donate-now input {
    display:block;
    position:absolute;
    top:0;
    left:0;
    right:0;
    bottom:0;
}

.donate-now input[type="radio"] {
    opacity:0.011;
    z-index:100;
}

.donate-now input[type="radio"]:checked + label {
    background:yellow;
}

.donate-now label {
     padding:5px;
     border:1px solid #CCC; 
     cursor:pointer;
    z-index:90;
}

.donate-now label:hover {
     background:#DDD;
}

您可以根据自己的样式对其进行自定义。

答案 1 :(得分:1)

您是否看过https://material-ui.com/components/toggle-button/https://material-ui.com/api/toggle-button-group/?我认为这是一个相对较新的功能(即您解决此问题时不存在),但对以后发现此问题的任何人可能会有帮助。

  

如果ToggleButtonGroup具有自己的值prop,它将控制其子按钮的选定状态。

这是该页面上给出的示例:

      <ToggleButtonGroup
        value={alignment}
        exclusive
        onChange={handleAlignment}
        aria-label="text alignment"
      >
        <ToggleButton value="left" aria-label="left aligned">
          <FormatAlignLeftIcon />
        </ToggleButton>
        <ToggleButton value="center" aria-label="centered">
          <FormatAlignCenterIcon />
        </ToggleButton>
        <ToggleButton value="right" aria-label="right aligned">
          <FormatAlignRightIcon />
        </ToggleButton>
        <ToggleButton value="justify" aria-label="justified" disabled>
          <FormatAlignJustifyIcon />
        </ToggleButton>
      </ToggleButtonGroup>