From 446818f02c2b45d4b3237db66a26b5d8ad6e0096 Mon Sep 17 00:00:00 2001 From: Praveenkumar Kalidass Date: Wed, 10 Mar 2021 03:10:15 +0530 Subject: [PATCH] [Stepper] Migrate StepIcon to emotion (#25281) --- docs/pages/api-docs/step-icon.json | 5 +- .../api-docs/step-icon/step-icon.json | 3 +- .../material-ui/src/StepIcon/StepIcon.d.ts | 6 + packages/material-ui/src/StepIcon/StepIcon.js | 144 ++++++++++++------ .../material-ui/src/StepIcon/StepIcon.test.js | 16 +- packages/material-ui/src/StepIcon/index.d.ts | 3 + packages/material-ui/src/StepIcon/index.js | 3 + .../src/StepIcon/stepIconClasses.d.ts | 7 + .../src/StepIcon/stepIconClasses.js | 15 ++ .../src/StepLabel/StepLabel.test.js | 4 +- 10 files changed, 148 insertions(+), 58 deletions(-) create mode 100644 packages/material-ui/src/StepIcon/stepIconClasses.d.ts create mode 100644 packages/material-ui/src/StepIcon/stepIconClasses.js diff --git a/docs/pages/api-docs/step-icon.json b/docs/pages/api-docs/step-icon.json index 5f11e44a5eee41..a45a4f4408acc1 100644 --- a/docs/pages/api-docs/step-icon.json +++ b/docs/pages/api-docs/step-icon.json @@ -4,7 +4,8 @@ "classes": { "type": { "name": "object" } }, "completed": { "type": { "name": "bool" } }, "error": { "type": { "name": "bool" } }, - "icon": { "type": { "name": "node" } } + "icon": { "type": { "name": "node" } }, + "sx": { "type": { "name": "object" } } }, "name": "StepIcon", "styles": { @@ -17,6 +18,6 @@ "filename": "/packages/material-ui/src/StepIcon/StepIcon.js", "inheritance": null, "demos": "", - "styledComponent": false, + "styledComponent": true, "cssComponent": false } diff --git a/docs/translations/api-docs/step-icon/step-icon.json b/docs/translations/api-docs/step-icon/step-icon.json index 5c84ff2c3c9e13..c382096d04d040 100644 --- a/docs/translations/api-docs/step-icon/step-icon.json +++ b/docs/translations/api-docs/step-icon/step-icon.json @@ -5,7 +5,8 @@ "classes": "Override or extend the styles applied to the component. See CSS API below for more details.", "completed": "Mark the step as completed. Is passed to child components.", "error": "If true, the step is marked as failed.", - "icon": "The label displayed in the step icon." + "icon": "The label displayed in the step icon.", + "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/StepIcon/StepIcon.d.ts b/packages/material-ui/src/StepIcon/StepIcon.d.ts index 1a9c78210a7a00..087ba202322d91 100644 --- a/packages/material-ui/src/StepIcon/StepIcon.d.ts +++ b/packages/material-ui/src/StepIcon/StepIcon.d.ts @@ -1,5 +1,7 @@ import * as React from 'react'; +import { SxProps } from '@material-ui/system'; import { InternalStandardProps as StandardProps } from '..'; +import { Theme } from '../styles'; export interface StepIconProps extends StandardProps, 'children'> { @@ -37,6 +39,10 @@ export interface StepIconProps * The label displayed in the step icon. */ icon: React.ReactNode; + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx?: SxProps; } export type StepIconClasskey = keyof NonNullable; diff --git a/packages/material-ui/src/StepIcon/StepIcon.js b/packages/material-ui/src/StepIcon/StepIcon.js index 50e1c48ebd0d8d..d45685c7cd02c1 100644 --- a/packages/material-ui/src/StepIcon/StepIcon.js +++ b/packages/material-ui/src/StepIcon/StepIcon.js @@ -1,47 +1,80 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import clsx from 'clsx'; +import { deepmerge } from '@material-ui/utils'; +import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled'; +import experimentalStyled from '../styles/experimentalStyled'; +import useThemeProps from '../styles/useThemeProps'; import CheckCircle from '../internal/svg-icons/CheckCircle'; import Warning from '../internal/svg-icons/Warning'; -import withStyles from '../styles/withStyles'; import SvgIcon from '../SvgIcon'; +import stepIconClasses, { getStepIconUtilityClass } from './stepIconClasses'; -export const styles = (theme) => ({ - /* Styles applied to the root element. */ - root: { - display: 'block', - transition: theme.transitions.create('color', { - duration: theme.transitions.duration.shortest, - }), - color: theme.palette.text.disabled, - '&$completed': { - color: theme.palette.primary.main, - }, - '&$active': { - color: theme.palette.primary.main, - }, - '&$error': { - color: theme.palette.error.main, +const overridesResolver = (props, styles) => { + return deepmerge( + { + [`& .${stepIconClasses.text}`]: styles.text, }, + styles.root || {}, + ); +}; + +const useUtilityClasses = (styleProps) => { + const { classes, active, completed, error } = styleProps; + + const slots = { + root: ['root', active && 'active', completed && 'completed', error && 'error'], + text: ['text'], + }; + + return composeClasses(slots, getStepIconUtilityClass, classes); +}; + +const StepIconRoot = experimentalStyled( + SvgIcon, + {}, + { + name: 'MuiStepIcon', + slot: 'Root', + overridesResolver, }, - /* Styles applied to the SVG text element. */ - text: { - fill: theme.palette.primary.contrastText, - fontSize: theme.typography.caption.fontSize, - fontFamily: theme.typography.fontFamily, +)(({ theme }) => ({ + /* Styles applied to the root element. */ + display: 'block', + transition: theme.transitions.create('color', { + duration: theme.transitions.duration.shortest, + }), + color: theme.palette.text.disabled, + [`&.${stepIconClasses.completed}`]: { + color: theme.palette.primary.main, }, - /* Pseudo-class applied to the root element if `active={true}`. */ - active: {}, - /* Pseudo-class applied to the root element if `completed={true}`. */ - completed: {}, - /* Pseudo-class applied to the root element if `error={true}`. */ - error: {}, -}); + [`&.${stepIconClasses.active}`]: { + color: theme.palette.primary.main, + }, + [`&.${stepIconClasses.error}`]: { + color: theme.palette.error.main, + }, +})); + +const StepIconText = experimentalStyled( + 'text', + {}, + { + name: 'MuiStepIcon', + slot: 'Text', + overridesResolver, + }, +)(({ theme }) => ({ + /* Styles applied to the SVG text element. */ + fill: theme.palette.primary.contrastText, + fontSize: theme.typography.caption.fontSize, + fontFamily: theme.typography.fontFamily, +})); -const StepIcon = React.forwardRef(function StepIcon(props, ref) { +const StepIcon = React.forwardRef(function StepIcon(inProps, ref) { + const props = useThemeProps({ props: inProps, name: 'MuiStepIcon' }); const { active = false, - classes, className: classNameProp, completed = false, error = false, @@ -49,28 +82,49 @@ const StepIcon = React.forwardRef(function StepIcon(props, ref) { ...other } = props; + const styleProps = { ...props, active, completed, error }; + const classes = useUtilityClasses(styleProps); + if (typeof icon === 'number' || typeof icon === 'string') { - const className = clsx(classNameProp, classes.root, { - [classes.active]: active, - [classes.error]: error, - [classes.completed]: completed, - }); + const className = clsx(classNameProp, classes.root); if (error) { - return ; + return ( + + ); } if (completed) { - return ; + return ( + + ); } return ( - + - + {icon} - - + + ); } @@ -109,6 +163,10 @@ StepIcon.propTypes /* remove-proptypes */ = { * The label displayed in the step icon. */ icon: PropTypes.node, + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.object, }; -export default withStyles(styles, { name: 'MuiStepIcon' })(StepIcon); +export default StepIcon; diff --git a/packages/material-ui/src/StepIcon/StepIcon.test.js b/packages/material-ui/src/StepIcon/StepIcon.test.js index 64b7c435892d05..54165bac4deb46 100644 --- a/packages/material-ui/src/StepIcon/StepIcon.test.js +++ b/packages/material-ui/src/StepIcon/StepIcon.test.js @@ -1,23 +1,21 @@ import * as React from 'react'; import { expect } from 'chai'; -import { createMount, getClasses, describeConformance, createClientRender } from 'test/utils'; -import StepIcon from './StepIcon'; +import { createMount, describeConformanceV5, createClientRender } from 'test/utils'; +import StepIcon, { stepIconClasses as classes } from '@material-ui/core/StepIcon'; describe('', () => { const render = createClientRender(); const mount = createMount(); - let classes; - before(() => { - classes = getClasses(); - }); - - describeConformance(, () => ({ + describeConformanceV5(, () => ({ classes, inheritComponent: 'svg', + render, mount, + muiName: 'MuiStepIcon', + testVariantProps: { completed: true }, refInstanceof: window.SVGSVGElement, - skip: ['componentProp'], + skip: ['componentProp', 'componentsProp'], })); it('renders when completed', () => { diff --git a/packages/material-ui/src/StepIcon/index.d.ts b/packages/material-ui/src/StepIcon/index.d.ts index cdb123198cc4da..3b8832746b07cf 100644 --- a/packages/material-ui/src/StepIcon/index.d.ts +++ b/packages/material-ui/src/StepIcon/index.d.ts @@ -1,2 +1,5 @@ export { default } from './StepIcon'; export * from './StepIcon'; + +export { default as stepIconClasses } from './stepIconClasses'; +export * from './stepIconClasses'; diff --git a/packages/material-ui/src/StepIcon/index.js b/packages/material-ui/src/StepIcon/index.js index 0ecb3263a80f27..555e6cf418581d 100644 --- a/packages/material-ui/src/StepIcon/index.js +++ b/packages/material-ui/src/StepIcon/index.js @@ -1 +1,4 @@ export { default } from './StepIcon'; + +export { default as stepIconClasses } from './stepIconClasses'; +export * from './stepIconClasses'; diff --git a/packages/material-ui/src/StepIcon/stepIconClasses.d.ts b/packages/material-ui/src/StepIcon/stepIconClasses.d.ts new file mode 100644 index 00000000000000..19ff9a6102df11 --- /dev/null +++ b/packages/material-ui/src/StepIcon/stepIconClasses.d.ts @@ -0,0 +1,7 @@ +import { StepIconClasskey } from './StepIcon'; + +declare const stepIconClasses: Record; + +export function getStepIconUtilityClass(slot: string): string; + +export default stepIconClasses; diff --git a/packages/material-ui/src/StepIcon/stepIconClasses.js b/packages/material-ui/src/StepIcon/stepIconClasses.js new file mode 100644 index 00000000000000..ad6f25b1ffa379 --- /dev/null +++ b/packages/material-ui/src/StepIcon/stepIconClasses.js @@ -0,0 +1,15 @@ +import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled'; + +export function getStepIconUtilityClass(slot) { + return generateUtilityClass('MuiStepIcon', slot); +} + +const stepIconClasses = generateUtilityClasses('MuiStepIcon', [ + 'root', + 'active', + 'completed', + 'error', + 'text', +]); + +export default stepIconClasses; diff --git a/packages/material-ui/src/StepLabel/StepLabel.test.js b/packages/material-ui/src/StepLabel/StepLabel.test.js index 707bb2fce1d75e..ea877709c23baf 100644 --- a/packages/material-ui/src/StepLabel/StepLabel.test.js +++ b/packages/material-ui/src/StepLabel/StepLabel.test.js @@ -4,18 +4,16 @@ import { getClasses, createClientRender, createMount, describeConformance } from import Typography, { typographyClasses } from '../Typography'; import Stepper from '../Stepper'; import Step from '../Step'; -import StepIcon from '../StepIcon'; +import { stepIconClasses as iconClasses } from '../StepIcon'; import StepLabel from './StepLabel'; describe('', () => { let classes; - let iconClasses; const mount = createMount({ strict: true }); const render = createClientRender(); before(() => { classes = getClasses(); - iconClasses = getClasses(); }); describeConformance(, () => ({