diff --git a/packages/mui-codemod/src/v6.0.0/styled/styled-v6.js b/packages/mui-codemod/src/v6.0.0/styled/styled-v6.js index 4bef0e598b7eed..eeef1e63699534 100644 --- a/packages/mui-codemod/src/v6.0.0/styled/styled-v6.js +++ b/packages/mui-codemod/src/v6.0.0/styled/styled-v6.js @@ -9,6 +9,27 @@ export default function styledV6(file, api, options) { const root = j(file.source); const printOptions = options.printOptions; + function createBuildStyle(key, upperBuildStyle) { + return function buildStyle(styleExpression) { + if (key) { + if (key.type === 'Identifier' || key.type === 'StringLiteral') { + return upperBuildStyle(j.objectExpression([j.objectProperty(key, styleExpression)])); + } + if (key.type === 'TemplateLiteral') { + return upperBuildStyle( + j.objectExpression([ + { + ...j.objectProperty(key, styleExpression), + computed: true, + }, + ]), + ); + } + } + return upperBuildStyle ? upperBuildStyle(styleExpression) : styleExpression; + }; + } + /** * * @param {import('ast-types').namedTypes.MemberExpression | import('ast-types').namedTypes.Identifier} node @@ -309,7 +330,7 @@ export default function styledV6(file, api, options) { } } - recurseObjectExpression({ node: objectExpression }); + recurseObjectExpression({ node: objectExpression, buildStyle: createBuildStyle() }); if (variants.length) { objectExpression.properties.push( @@ -343,13 +364,19 @@ export default function styledV6(file, api, options) { node: prop.value, parentNode: data.node, key: prop.key, + buildStyle: createBuildStyle(prop.key, data.buildStyle), replaceValue: (newValue) => { prop.value = newValue; }, modeStyles, }); } else { - recurseObjectExpression({ ...data, node: prop, parentNode: data.node }); + recurseObjectExpression({ + ...data, + node: prop, + parentNode: data.node, + buildStyle: createBuildStyle(prop.key, data.buildStyle), + }); } }); appendPaletteModeStyles(data.node, modeStyles); @@ -367,6 +394,8 @@ export default function styledV6(file, api, options) { style: data.node.argument.right, }; + const lastLength = variants.push({}); // preserve the order of the recursive calls + const modeStyles = {}; // to collect styles from `theme.palette.mode === '...'` variant.style.properties.forEach((prop) => { if (prop.type === 'ObjectProperty') { @@ -376,6 +405,7 @@ export default function styledV6(file, api, options) { parentNode: variant.style, props: variant.props, key: prop.key, + buildStyle: createBuildStyle(prop.key, data.buildStyle), replaceValue: (newValue) => { prop.value = newValue; }, @@ -387,15 +417,21 @@ export default function styledV6(file, api, options) { node: prop, parentNode: variant.style, props: variant.props, + buildStyle: createBuildStyle(prop.key, data.buildStyle), }); } }); appendPaletteModeStyles(variant.style, modeStyles); - variants.push(buildObjectAST(variant)); + variant.style = data.buildStyle(variant.style); + variants[lastLength - 1] = buildObjectAST(variant); removeProperty(data.parentNode, data.node); } if (data.node.argument.type === 'ConditionalExpression') { - recurseObjectExpression({ ...data, node: data.node.argument, parentNode: data.node }); + recurseObjectExpression({ + ...data, + node: data.node.argument, + parentNode: data.node, + }); removeProperty(data.parentNode, data.node); } } @@ -417,17 +453,10 @@ export default function styledV6(file, api, options) { if (data.props) { props = mergeProps(data.props, props); } - const styleVal = data.node.consequent; - let newStyle = styleVal; - if ( - data.key && - (data.key.type === 'Identifier' || data.key.type === 'StringLiteral') - ) { - newStyle = j.objectExpression([j.objectProperty(data.key, styleVal)]); - } + const styleVal = data.buildStyle(data.node.consequent); const variant = { props, - style: newStyle, + style: styleVal, }; variants.push(buildObjectAST(variant)); @@ -436,17 +465,10 @@ export default function styledV6(file, api, options) { if (data.props) { props2 = mergeProps(data.props, props2); } - const styleVal2 = data.node.alternate; - let newStyle2 = styleVal2; - if ( - data.key && - (data.key.type === 'Identifier' || data.key.type === 'StringLiteral') - ) { - newStyle2 = j.objectExpression([j.objectProperty(data.key, styleVal2)]); - } + const styleVal2 = data.buildStyle(data.node.alternate); const variant2 = { props: props2, - style: newStyle2, + style: styleVal2, }; variants.push(buildObjectAST(variant2)); if (data.parentNode?.type === 'ObjectExpression') { @@ -484,7 +506,7 @@ export default function styledV6(file, api, options) { ...data, node: expression, parentNode: data.parentNode, - key: data.key, + buildStyle: createBuildStyle(data.key, data.buildStyle), replaceValue: (newValue) => { data.node.expressions[index] = newValue; }, @@ -523,7 +545,7 @@ export default function styledV6(file, api, options) { j.stringLiteral(prop.key.name), ), ]), - style: j.objectExpression([j.objectProperty(data.key, prop.value)]), + style: data.buildStyle(prop.value), }), ); }); diff --git a/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.actual.js b/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.actual.js index 831808277ff08d..a6d9713613d6c1 100644 --- a/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.actual.js +++ b/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.actual.js @@ -58,3 +58,27 @@ const ImageListRoot = styled('ul')(({ ownerState }) => { }), }; }); + +const ImageListItemRoot = styled('li')(({ ownerState }) => ({ + display: 'block', + position: 'relative', + [`& .${imageListItemClasses.img}`]: { + objectFit: 'cover', + width: '100%', + height: '100%', + display: 'block', + ...(ownerState.variant === 'standard' && { + height: 'auto', + flexGrow: 1, + }), + '&:hover': { + '&[data-shape="circular"]': { + borderRadius: '50%', + ...(ownerState.variant === 'unique' && { + height: 'auto', + flexGrow: 1, + }), + }, + }, + }, +})); diff --git a/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.expected.js b/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.expected.js index d7aa53897b899b..6024e33fe6b402 100644 --- a/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.expected.js +++ b/packages/mui-codemod/src/v6.0.0/styled/test-cases/BasicStyled.expected.js @@ -117,3 +117,44 @@ const ImageListRoot = styled('ul')({ } }] }); + +const ImageListItemRoot = styled('li')(({ + display: 'block', + position: 'relative', + [`& .${imageListItemClasses.img}`]: { + objectFit: 'cover', + width: '100%', + height: '100%', + display: 'block', + '&:hover': { + '&[data-shape="circular"]': { + borderRadius: '50%' + }, + } + }, + variants: [{ + props: { + variant: 'standard' + }, + style: { + [`& .${imageListItemClasses.img}`]: { + height: 'auto', + flexGrow: 1, + } + } + }, { + props: { + variant: 'unique' + }, + style: { + [`& .${imageListItemClasses.img}`]: { + '&:hover': { + '&[data-shape="circular"]': { + height: 'auto', + flexGrow: 1, + } + } + } + } + }] +})); diff --git a/packages/mui-codemod/src/v6.0.0/styled/test-cases/ConditionalStyled.expected.js b/packages/mui-codemod/src/v6.0.0/styled/test-cases/ConditionalStyled.expected.js index cafe6f81cf1ffb..462436559d07e9 100644 --- a/packages/mui-codemod/src/v6.0.0/styled/test-cases/ConditionalStyled.expected.js +++ b/packages/mui-codemod/src/v6.0.0/styled/test-cases/ConditionalStyled.expected.js @@ -17,6 +17,13 @@ const LinearProgressBar1 = styled('span', { theme }) => ({ variants: [{ + props: { + variant: 'buffer' + }, + style: { + '&:hover': {} + } + }, { props: ( { variant, @@ -56,13 +63,6 @@ const LinearProgressBar1 = styled('span', { backgroundColor: 'currentColor', } } - }, { - props: { - variant: 'buffer' - }, - style: { - '&:hover': {} - } }, { props: ( { diff --git a/packages/mui-codemod/src/v6.0.0/styled/test-cases/NestedSpread.expected.js b/packages/mui-codemod/src/v6.0.0/styled/test-cases/NestedSpread.expected.js index f19cf12d71209d..36aec722aa4883 100644 --- a/packages/mui-codemod/src/v6.0.0/styled/test-cases/NestedSpread.expected.js +++ b/packages/mui-codemod/src/v6.0.0/styled/test-cases/NestedSpread.expected.js @@ -62,6 +62,16 @@ const Component = styled('div')(({ style: { marginRight: -12 } + }, { + props: ( + { + ownerState + } + ) => ownerState.color !== 'inherit' && + ownerState.color !== 'default', + style: { + color: palette?.main + } }, { props: ( { @@ -84,16 +94,6 @@ const Component = styled('div')(({ }, }, } - }, { - props: ( - { - ownerState - } - ) => ownerState.color !== 'inherit' && - ownerState.color !== 'default', - style: { - color: palette?.main - } }] }; }); diff --git a/packages/mui-material/src/FormHelperText/FormHelperText.js b/packages/mui-material/src/FormHelperText/FormHelperText.js index f8acae4f37d515..9a1a133b958a95 100644 --- a/packages/mui-material/src/FormHelperText/FormHelperText.js +++ b/packages/mui-material/src/FormHelperText/FormHelperText.js @@ -41,7 +41,7 @@ const FormHelperTextRoot = styled('p', { ownerState.filled && styles.filled, ]; }, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ color: (theme.vars || theme).palette.text.secondary, ...theme.typography.caption, textAlign: 'left', @@ -55,13 +55,23 @@ const FormHelperTextRoot = styled('p', { [`&.${formHelperTextClasses.error}`]: { color: (theme.vars || theme).palette.error.main, }, - ...(ownerState.size === 'small' && { - marginTop: 4, - }), - ...(ownerState.contained && { - marginLeft: 14, - marginRight: 14, - }), + variants: [ + { + props: { + size: 'small', + }, + style: { + marginTop: 4, + }, + }, + { + props: ({ ownerState }) => ownerState.contained, + style: { + marginLeft: 14, + marginRight: 14, + }, + }, + ], })); const FormHelperText = React.forwardRef(function FormHelperText(inProps, ref) { diff --git a/packages/mui-material/src/ImageList/ImageList.js b/packages/mui-material/src/ImageList/ImageList.js index 5a521234e12ef5..1bb5af39974eee 100644 --- a/packages/mui-material/src/ImageList/ImageList.js +++ b/packages/mui-material/src/ImageList/ImageList.js @@ -27,18 +27,23 @@ const ImageListRoot = styled('ul', { return [styles.root, styles[ownerState.variant]]; }, -})(({ ownerState }) => { - return { - display: 'grid', - overflowY: 'auto', - listStyle: 'none', - padding: 0, - // Add iOS momentum scrolling for iOS < 13.0 - WebkitOverflowScrolling: 'touch', - ...(ownerState.variant === 'masonry' && { - display: 'block', - }), - }; +})({ + display: 'grid', + overflowY: 'auto', + listStyle: 'none', + padding: 0, + // Add iOS momentum scrolling for iOS < 13.0 + WebkitOverflowScrolling: 'touch', + variants: [ + { + props: { + variant: 'masonry', + }, + style: { + display: 'block', + }, + }, + ], }); const ImageList = React.forwardRef(function ImageList(inProps, ref) { diff --git a/packages/mui-material/src/ImageListItem/ImageListItem.js b/packages/mui-material/src/ImageListItem/ImageListItem.js index 4efc8004bd0537..32d2472c1f14e2 100644 --- a/packages/mui-material/src/ImageListItem/ImageListItem.js +++ b/packages/mui-material/src/ImageListItem/ImageListItem.js @@ -34,32 +34,51 @@ const ImageListItemRoot = styled('li', { styles[ownerState.variant], ]; }, -})(({ ownerState }) => ({ +})({ display: 'block', position: 'relative', - ...(ownerState.variant === 'standard' && { - // For titlebar under list item - display: 'flex', - flexDirection: 'column', - }), - ...(ownerState.variant === 'woven' && { - height: '100%', - alignSelf: 'center', - '&:nth-of-type(even)': { - height: '70%', - }, - }), [`& .${imageListItemClasses.img}`]: { objectFit: 'cover', width: '100%', height: '100%', display: 'block', - ...(ownerState.variant === 'standard' && { - height: 'auto', - flexGrow: 1, - }), }, -})); + variants: [ + { + props: { + variant: 'standard', + }, + style: { + // For titlebar under list item + display: 'flex', + flexDirection: 'column', + }, + }, + { + props: { + variant: 'woven', + }, + style: { + height: '100%', + alignSelf: 'center', + '&:nth-of-type(even)': { + height: '70%', + }, + }, + }, + { + props: { + variant: 'standard', + }, + style: { + [`& .${imageListItemClasses.img}`]: { + height: 'auto', + flexGrow: 1, + }, + }, + }, + ], +}); const ImageListItem = React.forwardRef(function ImageListItem(inProps, ref) { const props = useThemeProps({ diff --git a/packages/mui-material/src/ImageListItemBar/ImageListItemBar.js b/packages/mui-material/src/ImageListItemBar/ImageListItemBar.js index beb348657dbc6b..4ec1ae66ce7fe2 100644 --- a/packages/mui-material/src/ImageListItemBar/ImageListItemBar.js +++ b/packages/mui-material/src/ImageListItemBar/ImageListItemBar.js @@ -34,7 +34,7 @@ const ImageListItemBarRoot = styled('div', { return [styles.root, styles[`position${capitalize(ownerState.position)}`]]; }, -})(({ theme, ownerState }) => { +})(({ theme }) => { return { position: 'absolute', left: 0, @@ -43,17 +43,34 @@ const ImageListItemBarRoot = styled('div', { display: 'flex', alignItems: 'center', fontFamily: theme.typography.fontFamily, - ...(ownerState.position === 'bottom' && { - bottom: 0, - }), - ...(ownerState.position === 'top' && { - top: 0, - }), - ...(ownerState.position === 'below' && { - position: 'relative', - background: 'transparent', - alignItems: 'normal', - }), + variants: [ + { + props: { + position: 'bottom', + }, + style: { + bottom: 0, + }, + }, + { + props: { + position: 'top', + }, + style: { + top: 0, + }, + }, + { + props: { + position: 'below', + }, + style: { + position: 'relative', + background: 'transparent', + alignItems: 'normal', + }, + }, + ], }; }); @@ -69,24 +86,35 @@ const ImageListItemBarTitleWrap = styled('div', { ownerState.actionIcon && styles[`titleWrapActionPos${capitalize(ownerState.actionPosition)}`], ]; }, -})(({ theme, ownerState }) => { +})(({ theme }) => { return { flexGrow: 1, padding: '12px 16px', color: (theme.vars || theme).palette.common.white, overflow: 'hidden', - ...(ownerState.position === 'below' && { - padding: '6px 0 12px', - color: 'inherit', - }), - ...(ownerState.actionIcon && - ownerState.actionPosition === 'left' && { - paddingLeft: 0, - }), - ...(ownerState.actionIcon && - ownerState.actionPosition === 'right' && { - paddingRight: 0, - }), + variants: [ + { + props: { + position: 'below', + }, + style: { + padding: '6px 0 12px', + color: 'inherit', + }, + }, + { + props: ({ ownerState }) => ownerState.actionIcon && ownerState.actionPosition === 'left', + style: { + paddingLeft: 0, + }, + }, + { + props: ({ ownerState }) => ownerState.actionIcon && ownerState.actionPosition === 'right', + style: { + paddingRight: 0, + }, + }, + ], }; }); @@ -129,12 +157,17 @@ const ImageListItemBarActionIcon = styled('div', { styles[`actionIconActionPos${capitalize(ownerState.actionPosition)}`], ]; }, -})(({ ownerState }) => { - return { - ...(ownerState.actionPosition === 'left' && { - order: -1, - }), - }; +})({ + variants: [ + { + props: { + actionPosition: 'left', + }, + style: { + order: -1, + }, + }, + ], }); const ImageListItemBar = React.forwardRef(function ImageListItemBar(inProps, ref) { diff --git a/packages/mui-material/src/ListItem/ListItem.js b/packages/mui-material/src/ListItem/ListItem.js index d60ee0e4892a8c..82bc5a8659cbed 100644 --- a/packages/mui-material/src/ListItem/ListItem.js +++ b/packages/mui-material/src/ListItem/ListItem.js @@ -70,7 +70,7 @@ export const ListItemRoot = styled('div', { name: 'MuiListItem', slot: 'Root', overridesResolver, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ display: 'flex', justifyContent: 'flex-start', alignItems: 'center', @@ -79,28 +79,6 @@ export const ListItemRoot = styled('div', { width: '100%', boxSizing: 'border-box', textAlign: 'left', - ...(!ownerState.disablePadding && { - paddingTop: 8, - paddingBottom: 8, - ...(ownerState.dense && { - paddingTop: 4, - paddingBottom: 4, - }), - ...(!ownerState.disableGutters && { - paddingLeft: 16, - paddingRight: 16, - }), - ...(!!ownerState.secondaryAction && { - // Add some space to avoid collision as `ListItemSecondaryAction` - // is absolutely positioned. - paddingRight: 48, - }), - }), - ...(!!ownerState.secondaryAction && { - [`& > .${listItemButtonClasses.root}`]: { - paddingRight: 48, - }, - }), [`&.${listItemClasses.focusVisible}`]: { backgroundColor: (theme.vars || theme).palette.action.focus, }, @@ -120,45 +98,98 @@ export const ListItemRoot = styled('div', { [`&.${listItemClasses.disabled}`]: { opacity: (theme.vars || theme).palette.action.disabledOpacity, }, - ...(ownerState.alignItems === 'flex-start' && { - alignItems: 'flex-start', - }), - ...(ownerState.divider && { - borderBottom: `1px solid ${(theme.vars || theme).palette.divider}`, - backgroundClip: 'padding-box', - }), - ...(ownerState.button && { - transition: theme.transitions.create('background-color', { - duration: theme.transitions.duration.shortest, - }), - '&:hover': { - textDecoration: 'none', - backgroundColor: (theme.vars || theme).palette.action.hover, - // Reset on touch devices, it doesn't add specificity - '@media (hover: none)': { - backgroundColor: 'transparent', + variants: [ + { + props: ({ ownerState }) => !ownerState.disablePadding, + style: { + paddingTop: 8, + paddingBottom: 8, }, }, - [`&.${listItemClasses.selected}:hover`]: { - backgroundColor: theme.vars - ? `rgba(${theme.vars.palette.primary.mainChannel} / calc(${theme.vars.palette.action.selectedOpacity} + ${theme.vars.palette.action.hoverOpacity}))` - : alpha( - theme.palette.primary.main, - theme.palette.action.selectedOpacity + theme.palette.action.hoverOpacity, - ), - // Reset on touch devices, it doesn't add specificity - '@media (hover: none)': { - backgroundColor: theme.vars - ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.selectedOpacity})` - : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity), + { + props: ({ ownerState }) => !ownerState.disablePadding && ownerState.dense, + style: { + paddingTop: 4, + paddingBottom: 4, }, }, - }), - ...(ownerState.hasSecondaryAction && { - // Add some space to avoid collision as `ListItemSecondaryAction` - // is absolutely positioned. - paddingRight: 48, - }), + { + props: ({ ownerState }) => !ownerState.disablePadding && !ownerState.disableGutters, + style: { + paddingLeft: 16, + paddingRight: 16, + }, + }, + { + props: ({ ownerState }) => !ownerState.disablePadding && !!ownerState.secondaryAction, + style: { + // Add some space to avoid collision as `ListItemSecondaryAction` + // is absolutely positioned. + paddingRight: 48, + }, + }, + { + props: ({ ownerState }) => !!ownerState.secondaryAction, + style: { + [`& > .${listItemButtonClasses.root}`]: { + paddingRight: 48, + }, + }, + }, + { + props: { + alignItems: 'flex-start', + }, + style: { + alignItems: 'flex-start', + }, + }, + { + props: ({ ownerState }) => ownerState.divider, + style: { + borderBottom: `1px solid ${(theme.vars || theme).palette.divider}`, + backgroundClip: 'padding-box', + }, + }, + { + props: ({ ownerState }) => ownerState.button, + style: { + transition: theme.transitions.create('background-color', { + duration: theme.transitions.duration.shortest, + }), + '&:hover': { + textDecoration: 'none', + backgroundColor: (theme.vars || theme).palette.action.hover, + // Reset on touch devices, it doesn't add specificity + '@media (hover: none)': { + backgroundColor: 'transparent', + }, + }, + [`&.${listItemClasses.selected}:hover`]: { + backgroundColor: theme.vars + ? `rgba(${theme.vars.palette.primary.mainChannel} / calc(${theme.vars.palette.action.selectedOpacity} + ${theme.vars.palette.action.hoverOpacity}))` + : alpha( + theme.palette.primary.main, + theme.palette.action.selectedOpacity + theme.palette.action.hoverOpacity, + ), + // Reset on touch devices, it doesn't add specificity + '@media (hover: none)': { + backgroundColor: theme.vars + ? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.selectedOpacity})` + : alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity), + }, + }, + }, + }, + { + props: ({ ownerState }) => ownerState.hasSecondaryAction, + style: { + // Add some space to avoid collision as `ListItemSecondaryAction` + // is absolutely positioned. + paddingRight: 48, + }, + }, + ], })); const ListItemContainer = styled('li', { diff --git a/packages/mui-material/src/ListItemAvatar/ListItemAvatar.js b/packages/mui-material/src/ListItemAvatar/ListItemAvatar.js index fa580dbcb2509f..e076be63c2d5c9 100644 --- a/packages/mui-material/src/ListItemAvatar/ListItemAvatar.js +++ b/packages/mui-material/src/ListItemAvatar/ListItemAvatar.js @@ -26,13 +26,20 @@ const ListItemAvatarRoot = styled('div', { return [styles.root, ownerState.alignItems === 'flex-start' && styles.alignItemsFlexStart]; }, -})(({ ownerState }) => ({ +})({ minWidth: 56, flexShrink: 0, - ...(ownerState.alignItems === 'flex-start' && { - marginTop: 8, - }), -})); + variants: [ + { + props: { + alignItems: 'flex-start', + }, + style: { + marginTop: 8, + }, + }, + ], +}); /** * A simple wrapper to apply `List` styles to an `Avatar`. diff --git a/packages/mui-material/src/ListItemButton/ListItemButton.js b/packages/mui-material/src/ListItemButton/ListItemButton.js index 58d025dba07928..f05cadc79adbde 100644 --- a/packages/mui-material/src/ListItemButton/ListItemButton.js +++ b/packages/mui-material/src/ListItemButton/ListItemButton.js @@ -52,7 +52,7 @@ const ListItemButtonRoot = styled(ButtonBase, { name: 'MuiListItemButton', slot: 'Root', overridesResolver, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ display: 'flex', flexGrow: 1, justifyContent: 'flex-start', @@ -108,21 +108,37 @@ const ListItemButtonRoot = styled(ButtonBase, { [`&.${listItemButtonClasses.disabled}`]: { opacity: (theme.vars || theme).palette.action.disabledOpacity, }, - ...(ownerState.divider && { - borderBottom: `1px solid ${(theme.vars || theme).palette.divider}`, - backgroundClip: 'padding-box', - }), - ...(ownerState.alignItems === 'flex-start' && { - alignItems: 'flex-start', - }), - ...(!ownerState.disableGutters && { - paddingLeft: 16, - paddingRight: 16, - }), - ...(ownerState.dense && { - paddingTop: 4, - paddingBottom: 4, - }), + variants: [ + { + props: ({ ownerState }) => ownerState.divider, + style: { + borderBottom: `1px solid ${(theme.vars || theme).palette.divider}`, + backgroundClip: 'padding-box', + }, + }, + { + props: { + alignItems: 'flex-start', + }, + style: { + alignItems: 'flex-start', + }, + }, + { + props: ({ ownerState }) => !ownerState.disableGutters, + style: { + paddingLeft: 16, + paddingRight: 16, + }, + }, + { + props: ({ ownerState }) => ownerState.dense, + style: { + paddingTop: 4, + paddingBottom: 4, + }, + }, + ], })); const ListItemButton = React.forwardRef(function ListItemButton(inProps, ref) { diff --git a/packages/mui-material/src/ListItemSecondaryAction/ListItemSecondaryAction.js b/packages/mui-material/src/ListItemSecondaryAction/ListItemSecondaryAction.js index 3b101be0640fe4..f098749fe6d35b 100644 --- a/packages/mui-material/src/ListItemSecondaryAction/ListItemSecondaryAction.js +++ b/packages/mui-material/src/ListItemSecondaryAction/ListItemSecondaryAction.js @@ -26,15 +26,20 @@ const ListItemSecondaryActionRoot = styled('div', { return [styles.root, ownerState.disableGutters && styles.disableGutters]; }, -})(({ ownerState }) => ({ +})({ position: 'absolute', right: 16, top: '50%', transform: 'translateY(-50%)', - ...(ownerState.disableGutters && { - right: 0, - }), -})); + variants: [ + { + props: ({ ownerState }) => ownerState.disableGutters, + style: { + right: 0, + }, + }, + ], +}); /** * Must be used as the last child of ListItem to function properly. diff --git a/packages/mui-material/src/ListItemText/ListItemText.js b/packages/mui-material/src/ListItemText/ListItemText.js index b5460439d37b9a..3c6af814ca33fb 100644 --- a/packages/mui-material/src/ListItemText/ListItemText.js +++ b/packages/mui-material/src/ListItemText/ListItemText.js @@ -36,20 +36,27 @@ const ListItemTextRoot = styled('div', { ownerState.dense && styles.dense, ]; }, -})(({ ownerState }) => ({ +})({ flex: '1 1 auto', minWidth: 0, marginTop: 4, marginBottom: 4, - ...(ownerState.primary && - ownerState.secondary && { - marginTop: 6, - marginBottom: 6, - }), - ...(ownerState.inset && { - paddingLeft: 56, - }), -})); + variants: [ + { + props: ({ ownerState }) => ownerState.primary && ownerState.secondary, + style: { + marginTop: 6, + marginBottom: 6, + }, + }, + { + props: ({ ownerState }) => ownerState.inset, + style: { + paddingLeft: 56, + }, + }, + ], +}); const ListItemText = React.forwardRef(function ListItemText(inProps, ref) { const props = useThemeProps({ props: inProps, name: 'MuiListItemText' }); diff --git a/packages/mui-material/src/ListSubheader/ListSubheader.js b/packages/mui-material/src/ListSubheader/ListSubheader.js index 668b3e9dd32dcf..3a869a9436baaf 100644 --- a/packages/mui-material/src/ListSubheader/ListSubheader.js +++ b/packages/mui-material/src/ListSubheader/ListSubheader.js @@ -38,7 +38,7 @@ const ListSubheaderRoot = styled('li', { !ownerState.disableSticky && styles.sticky, ]; }, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ boxSizing: 'border-box', lineHeight: '48px', listStyle: 'none', @@ -46,25 +46,46 @@ const ListSubheaderRoot = styled('li', { fontFamily: theme.typography.fontFamily, fontWeight: theme.typography.fontWeightMedium, fontSize: theme.typography.pxToRem(14), - ...(ownerState.color === 'primary' && { - color: (theme.vars || theme).palette.primary.main, - }), - ...(ownerState.color === 'inherit' && { - color: 'inherit', - }), - ...(!ownerState.disableGutters && { - paddingLeft: 16, - paddingRight: 16, - }), - ...(ownerState.inset && { - paddingLeft: 72, - }), - ...(!ownerState.disableSticky && { - position: 'sticky', - top: 0, - zIndex: 1, - backgroundColor: (theme.vars || theme).palette.background.paper, - }), + variants: [ + { + props: { + color: 'primary', + }, + style: { + color: (theme.vars || theme).palette.primary.main, + }, + }, + { + props: { + color: 'inherit', + }, + style: { + color: 'inherit', + }, + }, + { + props: ({ ownerState }) => !ownerState.disableGutters, + style: { + paddingLeft: 16, + paddingRight: 16, + }, + }, + { + props: ({ ownerState }) => ownerState.inset, + style: { + paddingLeft: 72, + }, + }, + { + props: ({ ownerState }) => !ownerState.disableSticky, + style: { + position: 'sticky', + top: 0, + zIndex: 1, + backgroundColor: (theme.vars || theme).palette.background.paper, + }, + }, + ], })); const ListSubheader = React.forwardRef(function ListSubheader(inProps, ref) { diff --git a/packages/mui-material/src/Rating/Rating.js b/packages/mui-material/src/Rating/Rating.js index 882e57bcf04e24..8e17b96b169371 100644 --- a/packages/mui-material/src/Rating/Rating.js +++ b/packages/mui-material/src/Rating/Rating.js @@ -73,7 +73,7 @@ const RatingRoot = styled('span', { ownerState.readOnly && styles.readOnly, ]; }, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ display: 'inline-flex', // Required to position the pristine input absolutely position: 'relative', @@ -91,16 +91,31 @@ const RatingRoot = styled('span', { outline: '1px solid #999', }, [`& .${ratingClasses.visuallyHidden}`]: visuallyHidden, - ...(ownerState.size === 'small' && { - fontSize: theme.typography.pxToRem(18), - }), - ...(ownerState.size === 'large' && { - fontSize: theme.typography.pxToRem(30), - }), - // TODO v6: use the .Mui-readOnly global state class - ...(ownerState.readOnly && { - pointerEvents: 'none', - }), + variants: [ + { + props: { + size: 'small', + }, + style: { + fontSize: theme.typography.pxToRem(18), + }, + }, + { + props: { + size: 'large', + }, + style: { + fontSize: theme.typography.pxToRem(30), + }, + }, + { + // TODO v6: use the .Mui-readOnly global state class + props: ({ ownerState }) => ownerState.readOnly, + style: { + pointerEvents: 'none', + }, + }, + ], })); const RatingLabel = styled('label', { @@ -110,16 +125,21 @@ const RatingLabel = styled('label', { styles.label, ownerState.emptyValueFocused && styles.labelEmptyValueActive, ], -})(({ ownerState }) => ({ +})({ cursor: 'inherit', - ...(ownerState.emptyValueFocused && { - top: 0, - bottom: 0, - position: 'absolute', - outline: '1px solid #999', - width: '100%', - }), -})); + variants: [ + { + props: ({ ownerState }) => ownerState.emptyValueFocused, + style: { + top: 0, + bottom: 0, + position: 'absolute', + outline: '1px solid #999', + width: '100%', + }, + }, + ], +}); const RatingIcon = styled('span', { name: 'MuiRating', @@ -136,7 +156,7 @@ const RatingIcon = styled('span', { ownerState.iconActive && styles.iconActive, ]; }, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ // Fit wrapper to actual icon size. display: 'flex', transition: theme.transitions.create('transform', { @@ -145,12 +165,20 @@ const RatingIcon = styled('span', { // Fix mouseLeave issue. // https://github.com/facebook/react/issues/4492 pointerEvents: 'none', - ...(ownerState.iconActive && { - transform: 'scale(1.2)', - }), - ...(ownerState.iconEmpty && { - color: (theme.vars || theme).palette.action.disabled, - }), + variants: [ + { + props: ({ ownerState }) => ownerState.iconActive, + style: { + transform: 'scale(1.2)', + }, + }, + { + props: ({ ownerState }) => ownerState.iconEmpty, + style: { + color: (theme.vars || theme).palette.action.disabled, + }, + }, + ], })); const RatingDecimal = styled('span', { @@ -162,12 +190,17 @@ const RatingDecimal = styled('span', { return [styles.decimal, iconActive && styles.iconActive]; }, -})(({ iconActive }) => ({ +})({ position: 'relative', - ...(iconActive && { - transform: 'scale(1.2)', - }), -})); + variants: [ + { + props: ({ iconActive }) => iconActive, + style: { + transform: 'scale(1.2)', + }, + }, + ], +}); function IconContainer(props) { const { value, ...other } = props; diff --git a/packages/mui-material/src/Table/Table.js b/packages/mui-material/src/Table/Table.js index 8690bf2017f2a0..ee4e793dcaa1d6 100644 --- a/packages/mui-material/src/Table/Table.js +++ b/packages/mui-material/src/Table/Table.js @@ -26,7 +26,7 @@ const TableRoot = styled('table', { return [styles.root, ownerState.stickyHeader && styles.stickyHeader]; }, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ display: 'table', width: '100%', borderCollapse: 'collapse', @@ -38,9 +38,14 @@ const TableRoot = styled('table', { textAlign: 'left', captionSide: 'bottom', }, - ...(ownerState.stickyHeader && { - borderCollapse: 'separate', - }), + variants: [ + { + props: ({ ownerState }) => ownerState.stickyHeader, + style: { + borderCollapse: 'separate', + }, + }, + ], })); const defaultComponent = 'table'; diff --git a/packages/mui-material/src/TableCell/TableCell.js b/packages/mui-material/src/TableCell/TableCell.js index 1b790f9e04c4e1..cf3860f2763af1 100644 --- a/packages/mui-material/src/TableCell/TableCell.js +++ b/packages/mui-material/src/TableCell/TableCell.js @@ -43,7 +43,7 @@ const TableCellRoot = styled('td', { ownerState.stickyHeader && styles.stickyHeader, ]; }, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ ...theme.typography.body2, display: 'table-cell', verticalAlign: 'inherit', @@ -59,55 +59,110 @@ const TableCellRoot = styled('td', { }`, textAlign: 'left', padding: 16, - ...(ownerState.variant === 'head' && { - color: (theme.vars || theme).palette.text.primary, - lineHeight: theme.typography.pxToRem(24), - fontWeight: theme.typography.fontWeightMedium, - }), - ...(ownerState.variant === 'body' && { - color: (theme.vars || theme).palette.text.primary, - }), - ...(ownerState.variant === 'footer' && { - color: (theme.vars || theme).palette.text.secondary, - lineHeight: theme.typography.pxToRem(21), - fontSize: theme.typography.pxToRem(12), - }), - ...(ownerState.size === 'small' && { - padding: '6px 16px', - [`&.${tableCellClasses.paddingCheckbox}`]: { - width: 24, // prevent the checkbox column from growing - padding: '0 12px 0 16px', - '& > *': { + variants: [ + { + props: { + variant: 'head', + }, + style: { + color: (theme.vars || theme).palette.text.primary, + lineHeight: theme.typography.pxToRem(24), + fontWeight: theme.typography.fontWeightMedium, + }, + }, + { + props: { + variant: 'body', + }, + style: { + color: (theme.vars || theme).palette.text.primary, + }, + }, + { + props: { + variant: 'footer', + }, + style: { + color: (theme.vars || theme).palette.text.secondary, + lineHeight: theme.typography.pxToRem(21), + fontSize: theme.typography.pxToRem(12), + }, + }, + { + props: { + size: 'small', + }, + style: { + padding: '6px 16px', + [`&.${tableCellClasses.paddingCheckbox}`]: { + width: 24, // prevent the checkbox column from growing + padding: '0 12px 0 16px', + '& > *': { + padding: 0, + }, + }, + }, + }, + { + props: { + padding: 'checkbox', + }, + style: { + width: 48, // prevent the checkbox column from growing + padding: '0 0 0 4px', + }, + }, + { + props: { + padding: 'none', + }, + style: { padding: 0, }, }, - }), - ...(ownerState.padding === 'checkbox' && { - width: 48, // prevent the checkbox column from growing - padding: '0 0 0 4px', - }), - ...(ownerState.padding === 'none' && { - padding: 0, - }), - ...(ownerState.align === 'left' && { - textAlign: 'left', - }), - ...(ownerState.align === 'center' && { - textAlign: 'center', - }), - ...(ownerState.align === 'right' && { - textAlign: 'right', - flexDirection: 'row-reverse', - }), - ...(ownerState.align === 'justify' && { - textAlign: 'justify', - }), - ...(ownerState.stickyHeader && { - position: 'sticky', - top: 0, - zIndex: 2, - backgroundColor: (theme.vars || theme).palette.background.default, - }), + { + props: { + align: 'left', + }, + style: { + textAlign: 'left', + }, + }, + { + props: { + align: 'center', + }, + style: { + textAlign: 'center', + }, + }, + { + props: { + align: 'right', + }, + style: { + textAlign: 'right', + flexDirection: 'row-reverse', + }, + }, + { + props: { + align: 'justify', + }, + style: { + textAlign: 'justify', + }, + }, + { + props: ({ ownerState }) => ownerState.stickyHeader, + style: { + position: 'sticky', + top: 0, + zIndex: 2, + backgroundColor: (theme.vars || theme).palette.background.default, + }, + }, + ], })); /** diff --git a/packages/mui-material/src/TableSortLabel/TableSortLabel.js b/packages/mui-material/src/TableSortLabel/TableSortLabel.js index 7031a61adebc1d..f2e174a41fb901 100644 --- a/packages/mui-material/src/TableSortLabel/TableSortLabel.js +++ b/packages/mui-material/src/TableSortLabel/TableSortLabel.js @@ -61,7 +61,7 @@ const TableSortLabelIcon = styled('span', { return [styles.icon, styles[`iconDirection${capitalize(ownerState.direction)}`]]; }, -})(({ theme, ownerState }) => ({ +})(({ theme }) => ({ fontSize: 18, marginRight: 4, marginLeft: 4, @@ -70,12 +70,24 @@ const TableSortLabelIcon = styled('span', { duration: theme.transitions.duration.shorter, }), userSelect: 'none', - ...(ownerState.direction === 'desc' && { - transform: 'rotate(0deg)', - }), - ...(ownerState.direction === 'asc' && { - transform: 'rotate(180deg)', - }), + variants: [ + { + props: { + direction: 'desc', + }, + style: { + transform: 'rotate(0deg)', + }, + }, + { + props: { + direction: 'asc', + }, + style: { + transform: 'rotate(180deg)', + }, + }, + ], })); /** diff --git a/packages/mui-material/src/Toolbar/Toolbar.js b/packages/mui-material/src/Toolbar/Toolbar.js index 070e1a54739974..2f9d903e189c05 100644 --- a/packages/mui-material/src/Toolbar/Toolbar.js +++ b/packages/mui-material/src/Toolbar/Toolbar.js @@ -26,23 +26,42 @@ const ToolbarRoot = styled('div', { return [styles.root, !ownerState.disableGutters && styles.gutters, styles[ownerState.variant]]; }, })( - ({ theme, ownerState }) => ({ + ({ theme }) => ({ position: 'relative', display: 'flex', alignItems: 'center', - ...(!ownerState.disableGutters && { - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), - [theme.breakpoints.up('sm')]: { - paddingLeft: theme.spacing(3), - paddingRight: theme.spacing(3), + variants: [ + { + props: ({ ownerState }) => !ownerState.disableGutters, + style: { + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + [theme.breakpoints.up('sm')]: { + paddingLeft: theme.spacing(3), + paddingRight: theme.spacing(3), + }, + }, }, - }), - ...(ownerState.variant === 'dense' && { - minHeight: 48, - }), + { + props: { + variant: 'dense', + }, + style: { + minHeight: 48, + }, + }, + ], + }), + ({ theme }) => ({ + variants: [ + { + props: { + variant: 'regular', + }, + style: theme.mixins.toolbar, + }, + ], }), - ({ theme, ownerState }) => ownerState.variant === 'regular' && theme.mixins.toolbar, ); const Toolbar = React.forwardRef(function Toolbar(inProps, ref) {