Skip to content

Commit

Permalink
[Radio] Migrate to emotion (#25152)
Browse files Browse the repository at this point in the history
  • Loading branch information
mngu committed Mar 3, 2021
1 parent 8ae56ff commit a1b75cc
Show file tree
Hide file tree
Showing 12 changed files with 125 additions and 78 deletions.
3 changes: 2 additions & 1 deletion docs/pages/api-docs/radio.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"type": { "name": "enum", "description": "'medium'<br>&#124;&nbsp;'small'" },
"default": "'medium'"
},
"sx": { "type": { "name": "object" } },
"value": { "type": { "name": "any" } }
},
"name": "Radio",
Expand All @@ -36,6 +37,6 @@
"filename": "/packages/material-ui/src/Radio/Radio.js",
"inheritance": { "component": "IconButton", "pathname": "/api/icon-button/" },
"demos": "<ul><li><a href=\"/components/radio-buttons/\">Radio Buttons</a></li></ul>",
"styledComponent": false,
"styledComponent": true,
"cssComponent": false
}
15 changes: 6 additions & 9 deletions docs/src/pages/components/radio-buttons/RadioButtons.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import * as React from 'react';
import { withStyles } from '@material-ui/core/styles';
import { experimentalStyled as styled } from '@material-ui/core/styles';
import { green } from '@material-ui/core/colors';
import Radio from '@material-ui/core/Radio';

const GreenRadio = withStyles({
root: {
color: green[400],
'&$checked': {
color: green[600],
},
const GreenRadio = styled(Radio)({
color: green[400],
'&.Mui-checked': {
color: green[600],
},
checked: {},
})((props) => <Radio color="default" {...props} />);
});

export default function RadioButtons() {
const [selectedValue, setSelectedValue] = React.useState('a');
Expand Down
17 changes: 7 additions & 10 deletions docs/src/pages/components/radio-buttons/RadioButtons.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import * as React from 'react';
import { withStyles } from '@material-ui/core/styles';
import { experimentalStyled as styled } from '@material-ui/core/styles';
import { green } from '@material-ui/core/colors';
import Radio, { RadioProps } from '@material-ui/core/Radio';
import Radio from '@material-ui/core/Radio';

const GreenRadio = withStyles({
root: {
color: green[400],
'&$checked': {
color: green[600],
},
const GreenRadio = styled(Radio)({
color: green[400],
'&.Mui-checked': {
color: green[600],
},
checked: {},
})((props: RadioProps) => <Radio color="default" {...props} />);
});

export default function RadioButtons() {
const [selectedValue, setSelectedValue] = React.useState('a');
Expand Down
1 change: 1 addition & 0 deletions docs/translations/api-docs/radio/radio.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"onChange": "Callback fired when the state is changed.<br><br><strong>Signature:</strong><br><code>function(event: object) =&gt; void</code><br><em>event:</em> The event source of the callback. You can pull out the new value by accessing <code>event.target.value</code> (string). You can pull out the new checked state by accessing <code>event.target.checked</code> (boolean).",
"required": "If <code>true</code>, the <code>input</code> element is required.",
"size": "The size of the component. <code>small</code> is equivalent to the dense radio styling.",
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/basics/#the-sx-prop\">`sx` page</a> for more details.",
"value": "The value of the component. The DOM API casts this to a string."
},
"classDescriptions": {
Expand Down
2 changes: 1 addition & 1 deletion framer/scripts/framerConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ export const componentSettings = {
template: 'paper.txt',
},
Radio: {
ignoredProps: ['checked', 'checkedIcon', 'icon', 'onChange', 'required', 'type', 'value'],
ignoredProps: ['checked', 'checkedIcon', 'icon', 'onChange', 'required', 'sx', 'type', 'value'],
propValues: {
label: "'Radio'",
width: "'100%'",
Expand Down
7 changes: 6 additions & 1 deletion packages/material-ui/src/Radio/Radio.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import { InternalStandardProps as StandardProps } from '..';
import { SxProps } from '@material-ui/system';
import { InternalStandardProps as StandardProps, Theme } from '..';
import { SwitchBaseProps } from '../internal/SwitchBase';

export interface RadioProps
Expand Down Expand Up @@ -42,6 +43,10 @@ export interface RadioProps
* @default 'medium'
*/
size?: 'small' | 'medium';
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
}

export type RadioClassKey = keyof NonNullable<RadioProps['classes']>;
Expand Down
108 changes: 63 additions & 45 deletions packages/material-ui/src/Radio/Radio.js
Original file line number Diff line number Diff line change
@@ -1,71 +1,88 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { refType } from '@material-ui/utils';
import { deepmerge, refType } from '@material-ui/utils';
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
import SwitchBase from '../internal/SwitchBase';
import useThemeProps from '../styles/useThemeProps';
import RadioButtonIcon from './RadioButtonIcon';
import { alpha } from '../styles/colorManipulator';
import capitalize from '../utils/capitalize';
import createChainedFunction from '../utils/createChainedFunction';
import withStyles from '../styles/withStyles';
import useRadioGroup from '../RadioGroup/useRadioGroup';
import { getRadioUtilityClass } from './radioClasses';
import experimentalStyled, { shouldForwardProp } from '../styles/experimentalStyled';

export const styles = (theme) => ({
/* Styles applied to the root element. */
root: {
color: theme.palette.text.secondary,
},
/* Pseudo-class applied to the root element if `checked={true}`. */
checked: {},
/* Pseudo-class applied to the root element if `disabled={true}`. */
disabled: {},
/* Styles applied to the root element if `color="primary"`. */
colorPrimary: {
'&$checked': {
color: theme.palette.primary.main,
'&:hover': {
backgroundColor: alpha(theme.palette.primary.main, theme.palette.action.hoverOpacity),
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor: 'transparent',
},
},
},
'&$disabled': {
color: theme.palette.action.disabled,
},
const overridesResolver = (props, styles) => {
const { styleProps } = props;

return deepmerge(styles.root || {}, styles[`color${capitalize(styleProps.color)}`]);
};

const useUtilityClasses = (styleProps) => {
const { classes, color } = styleProps;

const slots = {
root: ['root', `color${capitalize(color)}`],
};

return {
...classes,
...composeClasses(slots, getRadioUtilityClass, classes),
};
};

const RadioRoot = experimentalStyled(
SwitchBase,
{ shouldForwardProp: (prop) => shouldForwardProp(prop) || prop === 'classes' },
{
name: 'MuiRadio',
slot: 'Root',
overridesResolver,
},
/* Styles applied to the root element if `color="secondary"`. */
colorSecondary: {
'&$checked': {
color: theme.palette.secondary.main,
)(({ theme, styleProps }) => ({
/* Styles applied to the root element. */
color: theme.palette.text.secondary,
/* Styles applied to the root element unless `color="default"`. */
...(styleProps.color !== 'default' && {
'&.Mui-checked': {
color: theme.palette[styleProps.color].main,
'&:hover': {
backgroundColor: alpha(theme.palette.secondary.main, theme.palette.action.hoverOpacity),
backgroundColor: alpha(
theme.palette[styleProps.color].main,
theme.palette.action.hoverOpacity,
),
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor: 'transparent',
},
},
},
'&$disabled': {
color: theme.palette.action.disabled,
},
}),
'&.Mui-disabled': {
color: theme.palette.action.disabled,
},
});
}));

const defaultCheckedIcon = <RadioButtonIcon checked />;
const defaultIcon = <RadioButtonIcon />;

const Radio = React.forwardRef(function Radio(props, ref) {
const Radio = React.forwardRef(function Radio(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiRadio' });
const {
checked: checkedProp,
classes,
color = 'secondary',
name: nameProp,
onChange: onChangeProp,
size = 'medium',
...other
} = props;
const styleProps = {
...props,
color,
size,
};

const classes = useUtilityClasses(styleProps);
const radioGroup = useRadioGroup();

let checked = checkedProp;
Expand All @@ -82,18 +99,15 @@ const Radio = React.forwardRef(function Radio(props, ref) {
}

return (
<SwitchBase
<RadioRoot
color={color}
type="radio"
icon={React.cloneElement(defaultIcon, { fontSize: size === 'small' ? 'small' : 'medium' })}
checkedIcon={React.cloneElement(defaultCheckedIcon, {
fontSize: size === 'small' ? 'small' : 'medium',
})}
classes={{
root: clsx(classes.root, classes[`color${capitalize(color)}`]),
checked: classes.checked,
disabled: classes.disabled,
}}
styleProps={styleProps}
classes={classes}
name={name}
checked={checked}
onChange={onChange}
Expand Down Expand Up @@ -171,10 +185,14 @@ Radio.propTypes = {
* @default 'medium'
*/
size: PropTypes.oneOf(['medium', 'small']),
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.object,
/**
* The value of the component. The DOM API casts this to a string.
*/
value: PropTypes.any,
};

export default withStyles(styles, { name: 'MuiRadio' })(Radio);
export default Radio;
20 changes: 9 additions & 11 deletions packages/material-ui/src/Radio/Radio.test.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,23 @@
import * as React from 'react';
import { expect } from 'chai';
import { getClasses, createMount, describeConformance, createClientRender } from 'test/utils';
import FormControl from '../FormControl';
import IconButton from '../IconButton';
import Radio from './Radio';
import { createMount, describeConformanceV5, createClientRender } from 'test/utils';
import Radio, { radioClasses as classes } from '@material-ui/core/Radio';
import FormControl from '@material-ui/core/FormControl';
import IconButton from '@material-ui/core/IconButton';

describe('<Radio />', () => {
const render = createClientRender();
let classes;
const mount = createMount();

before(() => {
classes = getClasses(<Radio />);
});

describeConformance(<Radio />, () => ({
describeConformanceV5(<Radio />, () => ({
classes,
inheritComponent: IconButton,
render,
mount,
muiName: 'MuiRadio',
testVariantProps: { color: 'primary' },
refInstanceof: window.HTMLSpanElement,
skip: ['componentProp'],
skip: ['componentProp', 'componentsProp'],
}));

describe('styleSheet', () => {
Expand Down
3 changes: 3 additions & 0 deletions packages/material-ui/src/Radio/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export { default } from './Radio';
export * from './Radio';

export { default as radioClasses } from './radioClasses';
export * from './radioClasses';
3 changes: 3 additions & 0 deletions packages/material-ui/src/Radio/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { default } from './Radio';

export { default as radioClasses } from './radioClasses';
export * from './radioClasses';
9 changes: 9 additions & 0 deletions packages/material-ui/src/Radio/radioClasses.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { RadioClassKey } from './Radio';

export type RadioClasses = Record<RadioClassKey, string>;

declare const radioClasses: RadioClasses;

export function getRadioUtilityClass(slot: string): string;

export default radioClasses;
15 changes: 15 additions & 0 deletions packages/material-ui/src/Radio/radioClasses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled';

export function getRadioUtilityClass(slot) {
return generateUtilityClass('MuiRadio', slot);
}

const radioClasses = generateUtilityClasses('MuiRadio', [
'root',
'checked',
'disabled',
'colorPrimary',
'colorSecondary',
]);

export default radioClasses;

0 comments on commit a1b75cc

Please sign in to comment.