Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Radio][Checkbox] Add size="small" support #18688

1 change: 1 addition & 0 deletions docs/pages/api/checkbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ You can learn more about the difference by [reading this guide](/guides/minimizi
| <span class="prop-name">inputRef</span> | <span class="prop-type">ref</span> | | Pass a ref to the `input` element. |
| <span class="prop-name">onChange</span> | <span class="prop-type">func</span> | | Callback fired when the state is changed.<br><br>**Signature:**<br>`function(event: object) => void`<br>*event:* The event source of the callback. You can pull out the new checked state by accessing `event.target.checked` (boolean). |
| <span class="prop-name">required</span> | <span class="prop-type">bool</span> | | If `true`, the `input` element will be required. |
| <span class="prop-name">size</span> | <span class="prop-type">'small'<br>&#124;&nbsp;'medium'</span> | <span class="prop-default">'medium'</span> | The size of the checkbox. `small` is equivalent to the dense checkbox styling. |
| <span class="prop-name">type</span> | <span class="prop-type">string</span> | | The input component prop `type`. |
| <span class="prop-name">value</span> | <span class="prop-type">any</span> | | The value of the component. The DOM API casts this to a string. |

Expand Down
1 change: 1 addition & 0 deletions docs/pages/api/radio.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ You can learn more about the difference by [reading this guide](/guides/minimizi
| <span class="prop-name">name</span> | <span class="prop-type">string</span> | | Name attribute of the `input` element. |
| <span class="prop-name">onChange</span> | <span class="prop-type">func</span> | | Callback fired when the state is changed.<br><br>**Signature:**<br>`function(event: object) => void`<br>*event:* The event source of the callback. You can pull out the new value by accessing `event.target.value` (string). You can pull out the new checked state by accessing `event.target.checked` (boolean). |
| <span class="prop-name">required</span> | <span class="prop-type">bool</span> | | If `true`, the `input` element will be required. |
| <span class="prop-name">size</span> | <span class="prop-type">'small'<br>&#124;&nbsp;'medium'</span> | <span class="prop-default">'medium'</span> | The size of the radio. `small` is equivalent to the dense radio styling. |
| <span class="prop-name">type</span> | <span class="prop-type">string</span> | | The input component prop `type`. |
| <span class="prop-name">value</span> | <span class="prop-type">any</span> | | The value of the component. The DOM API casts this to a string. |

Expand Down
71 changes: 25 additions & 46 deletions docs/src/pages/components/checkboxes/Checkboxes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,51 @@ import React from 'react';
import Checkbox from '@material-ui/core/Checkbox';

export default function Checkboxes() {
const [state, setState] = React.useState({
checkedA: true,
checkedB: true,
checkedF: true,
});
const [checked, setChecked] = React.useState(true);

const handleChange = name => event => {
setState({ ...state, [name]: event.target.checked });
const handleChange = event => {
setChecked(event.target.checked);
};

return (
<div>
<Checkbox
checked={state.checkedA}
onChange={handleChange('checkedA')}
value="checkedA"
inputProps={{
'aria-label': 'primary checkbox',
}}
checked={checked}
onChange={handleChange}
value="primary"
inputProps={{ 'aria-label': 'primary checkbox' }}
/>
<Checkbox
checked={state.checkedB}
onChange={handleChange('checkedB')}
value="checkedB"
defaultChecked
value="secondary"
color="primary"
inputProps={{
'aria-label': 'secondary checkbox',
}}
/>
<Checkbox
value="checkedC"
inputProps={{
'aria-label': 'uncontrolled-checkbox',
}}
/>
<Checkbox
disabled
value="checkedD"
inputProps={{
'aria-label': 'disabled checkbox',
}}
inputProps={{ 'aria-label': 'secondary checkbox' }}
/>
<Checkbox value="uncontrolled" inputProps={{ 'aria-label': 'uncontrolled-checkbox' }} />
<Checkbox disabled value="disabled" inputProps={{ 'aria-label': 'disabled checkbox' }} />
<Checkbox
disabled
checked
value="checkedE"
inputProps={{
'aria-label': 'disabled checked checkbox',
}}
value="disabled checked"
inputProps={{ 'aria-label': 'disabled checked checkbox' }}
/>
<Checkbox
checked={state.checkedF}
onChange={handleChange('checkedF')}
value="checkedF"
defaultChecked
value="indeterminate"
indeterminate
inputProps={{
'aria-label': 'indeterminate checkbox',
}}
inputProps={{ 'aria-label': 'indeterminate checkbox' }}
/>
<Checkbox
defaultChecked
color="default"
value="checkedG"
inputProps={{
'aria-label': 'checkbox with default color',
}}
value="default"
inputProps={{ 'aria-label': 'checkbox with default color' }}
/>
<Checkbox
defaultChecked
size="small"
value="small"
inputProps={{ 'aria-label': 'checkbox with small size' }}
/>
</div>
);
Expand Down
71 changes: 25 additions & 46 deletions docs/src/pages/components/checkboxes/Checkboxes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,51 @@ import React from 'react';
import Checkbox from '@material-ui/core/Checkbox';

export default function Checkboxes() {
const [state, setState] = React.useState({
checkedA: true,
checkedB: true,
checkedF: true,
});
const [checked, setChecked] = React.useState(true);

const handleChange = (name: string) => (event: React.ChangeEvent<HTMLInputElement>) => {
setState({ ...state, [name]: event.target.checked });
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setChecked(event.target.checked);
};

return (
<div>
<Checkbox
checked={state.checkedA}
onChange={handleChange('checkedA')}
value="checkedA"
inputProps={{
'aria-label': 'primary checkbox',
}}
checked={checked}
onChange={handleChange}
value="primary"
inputProps={{ 'aria-label': 'primary checkbox' }}
/>
<Checkbox
checked={state.checkedB}
onChange={handleChange('checkedB')}
value="checkedB"
defaultChecked
value="secondary"
color="primary"
inputProps={{
'aria-label': 'secondary checkbox',
}}
/>
<Checkbox
value="checkedC"
inputProps={{
'aria-label': 'uncontrolled-checkbox',
}}
/>
<Checkbox
disabled
value="checkedD"
inputProps={{
'aria-label': 'disabled checkbox',
}}
inputProps={{ 'aria-label': 'secondary checkbox' }}
/>
<Checkbox value="uncontrolled" inputProps={{ 'aria-label': 'uncontrolled-checkbox' }} />
<Checkbox disabled value="disabled" inputProps={{ 'aria-label': 'disabled checkbox' }} />
<Checkbox
disabled
checked
value="checkedE"
inputProps={{
'aria-label': 'disabled checked checkbox',
}}
value="disabled checked"
inputProps={{ 'aria-label': 'disabled checked checkbox' }}
/>
<Checkbox
checked={state.checkedF}
onChange={handleChange('checkedF')}
value="checkedF"
defaultChecked
value="indeterminate"
indeterminate
inputProps={{
'aria-label': 'indeterminate checkbox',
}}
inputProps={{ 'aria-label': 'indeterminate checkbox' }}
/>
<Checkbox
defaultChecked
color="default"
value="checkedG"
inputProps={{
'aria-label': 'checkbox with default color',
}}
value="default"
inputProps={{ 'aria-label': 'checkbox with default color' }}
/>
<Checkbox
defaultChecked
size="small"
value="small"
inputProps={{ 'aria-label': 'checkbox with small size' }}
/>
</div>
);
Expand Down
5 changes: 1 addition & 4 deletions docs/src/pages/components/radio-buttons/RadioButtons.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import { green } from '@material-ui/core/colors';
import Radio from '@material-ui/core/Radio';
import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked';
import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked';

const GreenRadio = withStyles({
root: {
Expand Down Expand Up @@ -60,8 +58,7 @@ export default function RadioButtons() {
color="default"
name="radio-button-demo"
inputProps={{ 'aria-label': 'E' }}
icon={<RadioButtonUncheckedIcon fontSize="small" />}
checkedIcon={<RadioButtonCheckedIcon fontSize="small" />}
size="small"
/>
</div>
);
Expand Down
5 changes: 1 addition & 4 deletions docs/src/pages/components/radio-buttons/RadioButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import { green } from '@material-ui/core/colors';
import Radio, { RadioProps } from '@material-ui/core/Radio';
import RadioButtonUncheckedIcon from '@material-ui/icons/RadioButtonUnchecked';
import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked';

const GreenRadio = withStyles({
root: {
Expand Down Expand Up @@ -60,8 +58,7 @@ export default function RadioButtons() {
color="default"
name="radio-button-demo"
inputProps={{ 'aria-label': 'E' }}
icon={<RadioButtonUncheckedIcon fontSize="small" />}
checkedIcon={<RadioButtonCheckedIcon fontSize="small" />}
size="small"
/>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions packages/material-ui/src/Checkbox/Checkbox.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface CheckboxProps
icon?: React.ReactNode;
indeterminate?: boolean;
indeterminateIcon?: React.ReactNode;
size?: 'small' | 'medium';
}

export type CheckboxClassKey =
Expand Down
14 changes: 12 additions & 2 deletions packages/material-ui/src/Checkbox/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@ const Checkbox = React.forwardRef(function Checkbox(props, ref) {
indeterminate = false,
indeterminateIcon = defaultIndeterminateIcon,
inputProps,
size = 'medium',
...other
} = props;

return (
<SwitchBase
type="checkbox"
checkedIcon={indeterminate ? indeterminateIcon : checkedIcon}
classes={{
root: clsx(classes.root, classes[`color${capitalize(color)}`], {
[classes.indeterminate]: indeterminate,
Expand All @@ -88,7 +88,12 @@ const Checkbox = React.forwardRef(function Checkbox(props, ref) {
'data-indeterminate': indeterminate,
...inputProps,
}}
icon={indeterminate ? indeterminateIcon : icon}
icon={React.cloneElement(indeterminate ? indeterminateIcon : icon, {
fontSize: size === 'small' ? 'small' : 'default',
})}
checkedIcon={React.cloneElement(indeterminate ? indeterminateIcon : checkedIcon, {
fontSize: size === 'small' ? 'small' : 'default',
})}
ref={ref}
disabled={disabled}
{...other}
Expand Down Expand Up @@ -160,6 +165,11 @@ Checkbox.propTypes = {
* If `true`, the `input` element will be required.
*/
required: PropTypes.bool,
/**
* The size of the checkbox.
* `small` is equivalent to the dense checkbox styling.
*/
size: PropTypes.oneOf(['small', 'medium']),
/**
* The input component prop `type`.
*/
Expand Down
1 change: 1 addition & 0 deletions packages/material-ui/src/Radio/Radio.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface RadioProps
checkedIcon?: React.ReactNode;
color?: 'primary' | 'secondary' | 'default';
icon?: React.ReactNode;
size?: 'small' | 'medium';
}

export type RadioClassKey = SwitchBaseClassKey | 'colorPrimary' | 'colorSecondary';
Expand Down
12 changes: 10 additions & 2 deletions packages/material-ui/src/Radio/Radio.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const Radio = React.forwardRef(function Radio(props, ref) {
disabled = false,
name: nameProp,
onChange: onChangeProp,
size = 'medium',
...other
} = props;
const radioGroup = React.useContext(RadioGroupContext);
Expand All @@ -85,8 +86,10 @@ const Radio = React.forwardRef(function Radio(props, ref) {
<SwitchBase
color={color}
type="radio"
icon={defaultIcon}
checkedIcon={defaultCheckedIcon}
icon={React.cloneElement(defaultIcon, { fontSize: size === 'small' ? 'small' : 'default' })}
checkedIcon={React.cloneElement(defaultCheckedIcon, {
fontSize: size === 'small' ? 'small' : 'default',
})}
classes={{
root: clsx(classes.root, classes[`color${capitalize(color)}`]),
checked: classes.checked,
Expand Down Expand Up @@ -160,6 +163,11 @@ Radio.propTypes = {
* If `true`, the `input` element will be required.
*/
required: PropTypes.bool,
/**
* The size of the radio.
* `small` is equivalent to the dense radio styling.
*/
size: PropTypes.oneOf(['small', 'medium']),
/**
* The input component prop `type`.
*/
Expand Down
11 changes: 8 additions & 3 deletions packages/material-ui/src/Radio/RadioButtonIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ export const styles = theme => ({
* @ignore - internal component.
*/
function RadioButtonIcon(props) {
const { checked, classes } = props;
const { checked, classes, fontSize } = props;

return (
<div className={clsx(classes.root, { [classes.checked]: checked })}>
<RadioButtonUncheckedIcon />
<RadioButtonCheckedIcon className={classes.layer} />
<RadioButtonUncheckedIcon fontSize={fontSize} />
<RadioButtonCheckedIcon fontSize={fontSize} className={classes.layer} />
</div>
);
}
Expand All @@ -53,6 +53,11 @@ RadioButtonIcon.propTypes = {
* See [CSS API](#css) below for more details.
*/
classes: PropTypes.object.isRequired,
/**
* The size of the radio.
* `small` is equivalent to the dense radio styling.
*/
fontSize: PropTypes.oneOf(['small', 'default']),
};

export default withStyles(styles, { name: 'PrivateRadioButtonIcon' })(RadioButtonIcon);