diff --git a/docs/pages/api-docs/card-action-area.json b/docs/pages/api-docs/card-action-area.json index 1346871da259bb..39ba1e054d2895 100644 --- a/docs/pages/api-docs/card-action-area.json +++ b/docs/pages/api-docs/card-action-area.json @@ -1,7 +1,8 @@ { "props": { "children": { "type": { "name": "node" } }, - "classes": { "type": { "name": "object" } } + "classes": { "type": { "name": "object" } }, + "sx": { "type": { "name": "object" } } }, "name": "CardActionArea", "styles": { @@ -14,6 +15,6 @@ "filename": "/packages/material-ui/src/CardActionArea/CardActionArea.js", "inheritance": { "component": "ButtonBase", "pathname": "/api/button-base/" }, "demos": "", - "styledComponent": false, + "styledComponent": true, "cssComponent": false } diff --git a/docs/translations/api-docs/card-action-area/card-action-area.json b/docs/translations/api-docs/card-action-area/card-action-area.json index 8575bc36ac9361..13736a57bde5a8 100644 --- a/docs/translations/api-docs/card-action-area/card-action-area.json +++ b/docs/translations/api-docs/card-action-area/card-action-area.json @@ -2,7 +2,8 @@ "componentDescription": "", "propDescriptions": { "children": "The content of the component.", - "classes": "Override or extend the styles applied to the component. See CSS API below for more details." + "classes": "Override or extend the styles applied to the component. See CSS API below for more details.", + "sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the `sx` page for more details." }, "classDescriptions": { "root": { "description": "Styles applied to the root element." }, diff --git a/packages/material-ui/src/CardActionArea/CardActionArea.d.ts b/packages/material-ui/src/CardActionArea/CardActionArea.d.ts index 6c999917e09814..be6b0a3559d900 100644 --- a/packages/material-ui/src/CardActionArea/CardActionArea.d.ts +++ b/packages/material-ui/src/CardActionArea/CardActionArea.d.ts @@ -1,3 +1,5 @@ +import { SxProps } from '@material-ui/system'; +import { Theme } from '..'; import { ButtonBaseTypeMap, ExtendButtonBase, ExtendButtonBaseTypeMap } from '../ButtonBase'; import { OverrideProps } from '../OverridableComponent'; @@ -15,6 +17,10 @@ export type CardActionAreaTypeMap = ExtendButton focusHighlight?: string; }; focusVisibleClassName?: string; + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx?: SxProps; }; defaultComponent: D; }>; diff --git a/packages/material-ui/src/CardActionArea/CardActionArea.js b/packages/material-ui/src/CardActionArea/CardActionArea.js index ce4e11debdf6c7..3e2eacf454c0b6 100644 --- a/packages/material-ui/src/CardActionArea/CardActionArea.js +++ b/packages/material-ui/src/CardActionArea/CardActionArea.js @@ -1,58 +1,98 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import clsx from 'clsx'; -import withStyles from '../styles/withStyles'; +import { deepmerge } from '@material-ui/utils'; +import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled'; +import useThemeProps from '../styles/useThemeProps'; +import experimentalStyled from '../styles/experimentalStyled'; +import cardActionAreaClasses, { getCardActionAreaUtilityClass } from './cardActionAreaClasses'; import ButtonBase from '../ButtonBase'; -export const styles = (theme) => ({ +const overridesResolver = (props, styles) => { + return deepmerge(styles.root || {}, { + [`& .${cardActionAreaClasses.focusHighlight}`]: styles.focusHighlight, + }); +}; + +const useUtilityClasses = (styleProps) => { + const { classes } = styleProps; + + const slots = { + root: ['root'], + focusHighlight: ['focusHighlight'], + }; + + return composeClasses(slots, getCardActionAreaUtilityClass, classes); +}; + +const CardActionAreaRoot = experimentalStyled( + ButtonBase, + {}, + { + name: 'MuiCardActionArea', + slot: 'Root', + overridesResolver, + }, +)(({ theme }) => ({ /* Styles applied to the root element. */ - root: { - display: 'block', - textAlign: 'inherit', - width: '100%', - '&:hover $focusHighlight': { - opacity: theme.palette.action.hoverOpacity, - '@media (hover: none)': { - opacity: 0, - }, - }, - '&$focusVisible $focusHighlight': { - opacity: theme.palette.action.focusOpacity, + display: 'block', + textAlign: 'inherit', + width: '100%', + [`&:hover .${cardActionAreaClasses.focusHighlight}`]: { + opacity: theme.palette.action.hoverOpacity, + '@media (hover: none)': { + opacity: 0, }, }, - /* Pseudo-class applied to the ButtonBase root element if the action area is keyboard focused. */ - focusVisible: {}, - /* Styles applied to the overlay that covers the action area when it is keyboard focused. */ - focusHighlight: { - overflow: 'hidden', - pointerEvents: 'none', - position: 'absolute', - top: 0, - right: 0, - bottom: 0, - left: 0, - borderRadius: 'inherit', - opacity: 0, - backgroundColor: 'currentcolor', - transition: theme.transitions.create('opacity', { - duration: theme.transitions.duration.short, - }), + [`&.Mui-focusVisible .${cardActionAreaClasses.focusHighlight}`]: { + opacity: theme.palette.action.focusOpacity, }, -}); +})); + +const CardActionAreaFocusHighlight = experimentalStyled( + 'span', + {}, + { + name: 'MuiCardActionArea', + slot: 'FocusHighlight', + }, +)(({ theme }) => ({ + /* Styles applied to the overlay that covers the action area when it is keyboard focused. */ + overflow: 'hidden', + pointerEvents: 'none', + position: 'absolute', + top: 0, + right: 0, + bottom: 0, + left: 0, + borderRadius: 'inherit', + opacity: 0, + backgroundColor: 'currentcolor', + transition: theme.transitions.create('opacity', { + duration: theme.transitions.duration.short, + }), +})); -const CardActionArea = React.forwardRef(function CardActionArea(props, ref) { - const { children, classes, className, focusVisibleClassName, ...other } = props; +const CardActionArea = React.forwardRef(function CardActionArea(inProps, ref) { + const props = useThemeProps({ props: inProps, name: 'MuiCardActionArea' }); + const { children, className, focusVisibleClassName, ...other } = props; + + // TODO: convert to simple assignment after the type error in defaultPropsHandler.js:60:6 is fixed + const styleProps = { ...props }; + + const classes = useUtilityClasses(styleProps); return ( - {children} - - + + ); }); @@ -77,6 +117,10 @@ CardActionArea.propTypes = { * @ignore */ focusVisibleClassName: PropTypes.string, + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.object, }; -export default withStyles(styles, { name: 'MuiCardActionArea' })(CardActionArea); +export default CardActionArea; diff --git a/packages/material-ui/src/CardActionArea/CardActionArea.test.js b/packages/material-ui/src/CardActionArea/CardActionArea.test.js index 41d976938040b2..bfd2cc41ce83ee 100644 --- a/packages/material-ui/src/CardActionArea/CardActionArea.test.js +++ b/packages/material-ui/src/CardActionArea/CardActionArea.test.js @@ -1,21 +1,20 @@ import * as React from 'react'; -import { getClasses, createMount, describeConformance } from 'test/utils'; +import { createMount, describeConformanceV5 } from 'test/utils'; import ButtonBase from '../ButtonBase'; import CardActionArea from './CardActionArea'; +import classes from './cardActionAreaClasses'; describe('', () => { const mount = createMount(); - let classes; - before(() => { - classes = getClasses(); - }); - - describeConformance(, () => ({ + describeConformanceV5(, () => ({ classes, inheritComponent: ButtonBase, mount, + muiName: 'MuiCardActionArea', + testDeepOverrides: { slotName: 'focusHighlight', slotClassName: classes.focusHighlight }, + testVariantProps: { variant: 'foo' }, refInstanceof: window.HTMLButtonElement, - skip: ['componentProp'], + skip: ['componentProp', 'componentsProp'], })); }); diff --git a/packages/material-ui/src/CardActionArea/cardActionAreaClasses.d.ts b/packages/material-ui/src/CardActionArea/cardActionAreaClasses.d.ts new file mode 100644 index 00000000000000..71c71ff96aac5d --- /dev/null +++ b/packages/material-ui/src/CardActionArea/cardActionAreaClasses.d.ts @@ -0,0 +1,11 @@ +export interface CardActionAreaClasses { + root: string; + focusVisible: string; + focusHighlight: string; +} + +declare const cardActionAreaClasses: CardActionAreaClasses; + +export function getCardActionAreaUtilityClass(slot: string): string; + +export default cardActionAreaClasses; diff --git a/packages/material-ui/src/CardActionArea/cardActionAreaClasses.js b/packages/material-ui/src/CardActionArea/cardActionAreaClasses.js new file mode 100644 index 00000000000000..26f26673239eed --- /dev/null +++ b/packages/material-ui/src/CardActionArea/cardActionAreaClasses.js @@ -0,0 +1,13 @@ +import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled'; + +export function getCardActionAreaUtilityClass(slot) { + return generateUtilityClass('MuiCardActionArea', slot); +} + +const cardActionAreaClasses = generateUtilityClasses('MuiCardActionArea', [ + 'root', + 'focusVisible', + 'focusHighlight', +]); + +export default cardActionAreaClasses; diff --git a/packages/material-ui/src/CardActionArea/index.d.ts b/packages/material-ui/src/CardActionArea/index.d.ts index cbd52c732daa2a..85879d425e9168 100644 --- a/packages/material-ui/src/CardActionArea/index.d.ts +++ b/packages/material-ui/src/CardActionArea/index.d.ts @@ -1,2 +1,5 @@ export { default } from './CardActionArea'; export * from './CardActionArea'; + +export { default as cardActionAreaClasses } from './cardActionAreaClasses'; +export * from './cardActionAreaClasses'; diff --git a/packages/material-ui/src/CardActionArea/index.js b/packages/material-ui/src/CardActionArea/index.js index 92970de4509b97..88e3b45b30a7e0 100644 --- a/packages/material-ui/src/CardActionArea/index.js +++ b/packages/material-ui/src/CardActionArea/index.js @@ -1 +1,4 @@ export { default } from './CardActionArea'; + +export { default as cardActionAreaClasses } from './cardActionAreaClasses'; +export * from './cardActionAreaClasses';