diff --git a/docs/pages/api-docs/radio.json b/docs/pages/api-docs/radio.json
index c7499080bd807c..24bb15c5606d7e 100644
--- a/docs/pages/api-docs/radio.json
+++ b/docs/pages/api-docs/radio.json
@@ -23,6 +23,7 @@
"type": { "name": "enum", "description": "'medium'
| 'small'" },
"default": "'medium'"
},
+ "sx": { "type": { "name": "object" } },
"value": { "type": { "name": "any" } }
},
"name": "Radio",
@@ -36,6 +37,6 @@
"filename": "/packages/material-ui/src/Radio/Radio.js",
"inheritance": { "component": "IconButton", "pathname": "/api/icon-button/" },
"demos": "
",
- "styledComponent": false,
+ "styledComponent": true,
"cssComponent": false
}
diff --git a/docs/src/pages/components/radio-buttons/RadioButtons.js b/docs/src/pages/components/radio-buttons/RadioButtons.js
index 5973ff989332ca..650a2ac80c2c6b 100644
--- a/docs/src/pages/components/radio-buttons/RadioButtons.js
+++ b/docs/src/pages/components/radio-buttons/RadioButtons.js
@@ -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) => );
+});
export default function RadioButtons() {
const [selectedValue, setSelectedValue] = React.useState('a');
diff --git a/docs/src/pages/components/radio-buttons/RadioButtons.tsx b/docs/src/pages/components/radio-buttons/RadioButtons.tsx
index a769efdf3d809f..a337bbdcdd0b61 100644
--- a/docs/src/pages/components/radio-buttons/RadioButtons.tsx
+++ b/docs/src/pages/components/radio-buttons/RadioButtons.tsx
@@ -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) => );
+});
export default function RadioButtons() {
const [selectedValue, setSelectedValue] = React.useState('a');
diff --git a/docs/translations/api-docs/radio/radio.json b/docs/translations/api-docs/radio/radio.json
index 97f080c3fb2405..790eb163168949 100644
--- a/docs/translations/api-docs/radio/radio.json
+++ b/docs/translations/api-docs/radio/radio.json
@@ -15,6 +15,7 @@
"onChange": "Callback fired when the state is changed.
Signature:
function(event: object) => void
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).",
"required": "If true
, the input
element is required.",
"size": "The size of the component. small
is equivalent to the dense radio styling.",
+ "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details.",
"value": "The value of the component. The DOM API casts this to a string."
},
"classDescriptions": {
diff --git a/framer/scripts/framerConfig.js b/framer/scripts/framerConfig.js
index 70abc26ce22bda..1ac67631276411 100644
--- a/framer/scripts/framerConfig.js
+++ b/framer/scripts/framerConfig.js
@@ -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%'",
diff --git a/packages/material-ui/src/Radio/Radio.d.ts b/packages/material-ui/src/Radio/Radio.d.ts
index 0ae2a583dd00d8..cbceadd0179f48 100644
--- a/packages/material-ui/src/Radio/Radio.d.ts
+++ b/packages/material-ui/src/Radio/Radio.d.ts
@@ -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
@@ -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;
}
export type RadioClassKey = keyof NonNullable;
diff --git a/packages/material-ui/src/Radio/Radio.js b/packages/material-ui/src/Radio/Radio.js
index 39c6ccf93aa580..54c99379b15a85 100644
--- a/packages/material-ui/src/Radio/Radio.js
+++ b/packages/material-ui/src/Radio/Radio.js
@@ -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 = ;
const defaultIcon = ;
-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;
@@ -82,18 +99,15 @@ const Radio = React.forwardRef(function Radio(props, ref) {
}
return (
- ', () => {
const render = createClientRender();
- let classes;
const mount = createMount();
- before(() => {
- classes = getClasses();
- });
-
- describeConformance(, () => ({
+ describeConformanceV5(, () => ({
classes,
inheritComponent: IconButton,
+ render,
mount,
+ muiName: 'MuiRadio',
+ testVariantProps: { color: 'primary' },
refInstanceof: window.HTMLSpanElement,
- skip: ['componentProp'],
+ skip: ['componentProp', 'componentsProp'],
}));
describe('styleSheet', () => {
diff --git a/packages/material-ui/src/Radio/index.d.ts b/packages/material-ui/src/Radio/index.d.ts
index 9aef9464bf6c10..e3e9d1bea1a73e 100644
--- a/packages/material-ui/src/Radio/index.d.ts
+++ b/packages/material-ui/src/Radio/index.d.ts
@@ -1,2 +1,5 @@
export { default } from './Radio';
export * from './Radio';
+
+export { default as radioClasses } from './radioClasses';
+export * from './radioClasses';
diff --git a/packages/material-ui/src/Radio/index.js b/packages/material-ui/src/Radio/index.js
index 61c95671a551bb..659d29e9fd37fb 100644
--- a/packages/material-ui/src/Radio/index.js
+++ b/packages/material-ui/src/Radio/index.js
@@ -1 +1,4 @@
export { default } from './Radio';
+
+export { default as radioClasses } from './radioClasses';
+export * from './radioClasses';
diff --git a/packages/material-ui/src/Radio/radioClasses.d.ts b/packages/material-ui/src/Radio/radioClasses.d.ts
new file mode 100644
index 00000000000000..f315a60ead62f6
--- /dev/null
+++ b/packages/material-ui/src/Radio/radioClasses.d.ts
@@ -0,0 +1,9 @@
+import { RadioClassKey } from './Radio';
+
+export type RadioClasses = Record;
+
+declare const radioClasses: RadioClasses;
+
+export function getRadioUtilityClass(slot: string): string;
+
+export default radioClasses;
diff --git a/packages/material-ui/src/Radio/radioClasses.js b/packages/material-ui/src/Radio/radioClasses.js
new file mode 100644
index 00000000000000..c8ea3b7ca086fb
--- /dev/null
+++ b/packages/material-ui/src/Radio/radioClasses.js
@@ -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;