Skip to content

Commit 0327bb3

Browse files
authored
[Stepper] Migrate MobileStepper to emotion (#25589)
1 parent d2e0076 commit 0327bb3

File tree

9 files changed

+168
-61
lines changed

9 files changed

+168
-61
lines changed

docs/pages/api-docs/mobile-stepper.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
},
1414
"default": "'bottom'"
1515
},
16+
"sx": { "type": { "name": "object" } },
1617
"variant": {
1718
"type": {
1819
"name": "enum",
@@ -41,6 +42,6 @@
4142
"filename": "/packages/material-ui/src/MobileStepper/MobileStepper.js",
4243
"inheritance": { "component": "Paper", "pathname": "/api/paper/" },
4344
"demos": "<ul><li><a href=\"/components/steppers/\">Steppers</a></li></ul>",
44-
"styledComponent": false,
45+
"styledComponent": true,
4546
"cssComponent": false
4647
}

docs/translations/api-docs/mobile-stepper/mobile-stepper.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"nextButton": "A next button element. For instance, it can be a <code>Button</code> or an <code>IconButton</code>.",
99
"position": "Set the positioning type.",
1010
"steps": "The total steps.",
11+
"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.",
1112
"variant": "The variant to use."
1213
},
1314
"classDescriptions": {

packages/material-ui/src/MobileStepper/MobileStepper.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react';
2-
import { InternalStandardProps as StandardProps } from '..';
2+
import { SxProps } from '@material-ui/system';
3+
import { InternalStandardProps as StandardProps, Theme } from '..';
34
import { PaperProps } from '../Paper';
45
import { LinearProgressProps } from '../LinearProgress';
56

@@ -52,6 +53,10 @@ export interface MobileStepperProps extends StandardProps<PaperProps, 'children'
5253
* The total steps.
5354
*/
5455
steps: number;
56+
/**
57+
* The system prop that allows defining system overrides as well as additional CSS styles.
58+
*/
59+
sx?: SxProps<Theme>;
5560
/**
5661
* The variant to use.
5762
* @default 'dots'

packages/material-ui/src/MobileStepper/MobileStepper.js

Lines changed: 116 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,101 @@
11
import * as React from 'react';
22
import PropTypes from 'prop-types';
33
import clsx from 'clsx';
4-
import { integerPropType } from '@material-ui/utils';
5-
import withStyles from '../styles/withStyles';
4+
import { integerPropType, deepmerge } from '@material-ui/utils';
5+
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
66
import Paper from '../Paper';
77
import capitalize from '../utils/capitalize';
88
import LinearProgress from '../LinearProgress';
99

10-
export const styles = (theme) => ({
11-
/* Styles applied to the root element. */
12-
root: {
13-
display: 'flex',
14-
flexDirection: 'row',
15-
justifyContent: 'space-between',
16-
alignItems: 'center',
17-
background: theme.palette.background.default,
18-
padding: 8,
10+
import useThemeProps from '../styles/useThemeProps';
11+
import experimentalStyled from '../styles/experimentalStyled';
12+
import mobileStepperClasses, { getMobileStepperUtilityClass } from './mobileStepperClasses';
13+
14+
const overridesResolver = (props, styles) => {
15+
const { styleProps } = props;
16+
17+
return deepmerge(
18+
{
19+
...styles[`position${capitalize(styleProps.position)}`],
20+
[`& .${mobileStepperClasses.dots}`]: styles.dots,
21+
[`& .${mobileStepperClasses.dot}`]: {
22+
...styles.dot,
23+
...(styleProps.dotActive && styles.dotActive),
24+
},
25+
[`& .${mobileStepperClasses.dotActive}`]: styles.dotActive,
26+
[`& .${mobileStepperClasses.progress}`]: styles.progress,
27+
},
28+
styles.root || {},
29+
);
30+
};
31+
32+
const useUtilityClasses = (styleProps) => {
33+
const { classes, position } = styleProps;
34+
35+
const slots = {
36+
root: ['root', `position${capitalize(position)}`],
37+
dots: ['dots'],
38+
dot: ['dot'],
39+
dotActive: ['dotActive'],
40+
progress: ['progress'],
41+
};
42+
43+
return composeClasses(slots, getMobileStepperUtilityClass, classes);
44+
};
45+
46+
const MobileStepperRoot = experimentalStyled(
47+
Paper,
48+
{},
49+
{
50+
name: 'MuiMobileStepper',
51+
slot: 'Root',
52+
overridesResolver,
1953
},
54+
)(({ theme, styleProps }) => ({
55+
/* Styles applied to the root element. */
56+
display: 'flex',
57+
flexDirection: 'row',
58+
justifyContent: 'space-between',
59+
alignItems: 'center',
60+
background: theme.palette.background.default,
61+
padding: 8,
2062
/* Styles applied to the root element if `position="bottom"`. */
21-
positionBottom: {
63+
...(styleProps.position === 'bottom' && {
2264
position: 'fixed',
2365
bottom: 0,
2466
left: 0,
2567
right: 0,
2668
zIndex: theme.zIndex.mobileStepper,
27-
},
69+
}),
2870
/* Styles applied to the root element if `position="top"`. */
29-
positionTop: {
71+
...(styleProps.position === 'top' && {
3072
position: 'fixed',
3173
top: 0,
3274
left: 0,
3375
right: 0,
3476
zIndex: theme.zIndex.mobileStepper,
35-
},
36-
/* Styles applied to the root element if `position="static"`. */
37-
positionStatic: {},
77+
}),
78+
}));
79+
80+
const MobileStepperDots = experimentalStyled(
81+
'div',
82+
{},
83+
{ name: 'MuiMobileStepper', slot: 'Dots' },
84+
)(({ styleProps }) => ({
3885
/* Styles applied to the dots container if `variant="dots"`. */
39-
dots: {
86+
...(styleProps.variant === 'dots' && {
4087
display: 'flex',
4188
flexDirection: 'row',
42-
},
89+
}),
90+
}));
91+
92+
const MobileStepperDot = experimentalStyled(
93+
'div',
94+
{},
95+
{ name: 'MuiMobileStepper', slot: 'Dot' },
96+
)(({ theme, styleProps }) => ({
4397
/* Styles applied to each dot if `variant="dots"`. */
44-
dot: {
98+
...(styleProps.variant === 'dots' && {
4599
transition: theme.transitions.create('background-color', {
46100
duration: theme.transitions.duration.shortest,
47101
}),
@@ -50,22 +104,29 @@ export const styles = (theme) => ({
50104
width: 8,
51105
height: 8,
52106
margin: '0 2px',
53-
},
54-
/* Styles applied to a dot if `variant="dots"` and this is the active step. */
55-
dotActive: {
56-
backgroundColor: theme.palette.primary.main,
57-
},
107+
/* Styles applied to a dot if `variant="dots"` and this is the active step. */
108+
...(styleProps.dotActive && {
109+
backgroundColor: theme.palette.primary.main,
110+
}),
111+
}),
112+
}));
113+
114+
const MobileStepperProgress = experimentalStyled(
115+
LinearProgress,
116+
{},
117+
{ name: 'MuiMobileStepper', slot: 'Progress' },
118+
)(({ styleProps }) => ({
58119
/* Styles applied to the Linear Progress component if `variant="progress"`. */
59-
progress: {
120+
...(styleProps.variant === 'progress' && {
60121
width: '50%',
61-
},
62-
});
122+
}),
123+
}));
63124

64-
const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
125+
const MobileStepper = React.forwardRef(function MobileStepper(inProps, ref) {
126+
const props = useThemeProps({ props: inProps, name: 'MuiMobileStepper' });
65127
const {
66128
activeStep = 0,
67129
backButton,
68-
classes,
69130
className,
70131
LinearProgressProps,
71132
nextButton,
@@ -75,12 +136,22 @@ const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
75136
...other
76137
} = props;
77138

139+
const styleProps = {
140+
...props,
141+
activeStep,
142+
position,
143+
variant,
144+
};
145+
146+
const classes = useUtilityClasses(styleProps);
147+
78148
return (
79-
<Paper
149+
<MobileStepperRoot
80150
square
81151
elevation={0}
82-
className={clsx(classes.root, classes[`position${capitalize(position)}`], className)}
152+
className={clsx(classes.root, className)}
83153
ref={ref}
154+
styleProps={styleProps}
84155
{...other}
85156
>
86157
{backButton}
@@ -91,20 +162,20 @@ const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
91162
)}
92163

93164
{variant === 'dots' && (
94-
<div className={classes.dots}>
165+
<MobileStepperDots styleProps={styleProps} className={classes.dots}>
95166
{[...new Array(steps)].map((_, index) => (
96-
<div
167+
<MobileStepperDot
97168
key={index}
98-
className={clsx(classes.dot, {
99-
[classes.dotActive]: index === activeStep,
100-
})}
169+
className={clsx(classes.dot, { [classes.dotActive]: index === activeStep })}
170+
styleProps={{ ...styleProps, dotActive: index === activeStep }}
101171
/>
102172
))}
103-
</div>
173+
</MobileStepperDots>
104174
)}
105175

106176
{variant === 'progress' && (
107-
<LinearProgress
177+
<MobileStepperProgress
178+
styleProps={styleProps}
108179
className={classes.progress}
109180
variant="determinate"
110181
value={Math.ceil((activeStep / (steps - 1)) * 100)}
@@ -113,7 +184,7 @@ const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
113184
)}
114185

115186
{nextButton}
116-
</Paper>
187+
</MobileStepperRoot>
117188
);
118189
});
119190

@@ -157,11 +228,15 @@ MobileStepper.propTypes /* remove-proptypes */ = {
157228
* The total steps.
158229
*/
159230
steps: integerPropType.isRequired,
231+
/**
232+
* The system prop that allows defining system overrides as well as additional CSS styles.
233+
*/
234+
sx: PropTypes.object,
160235
/**
161236
* The variant to use.
162237
* @default 'dots'
163238
*/
164239
variant: PropTypes.oneOf(['dots', 'progress', 'text']),
165240
};
166241

167-
export default withStyles(styles, { name: 'MuiMobileStepper' })(MobileStepper);
242+
export default MobileStepper;

packages/material-ui/src/MobileStepper/MobileStepper.test.js

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
11
import * as React from 'react';
22
import { expect } from 'chai';
3-
import {
4-
getClasses,
5-
createMount,
6-
createClientRender,
7-
describeConformance,
8-
screen,
9-
} from 'test/utils';
10-
import KeyboardArrowLeft from '../internal/svg-icons/KeyboardArrowLeft';
3+
import { createMount, createClientRender, describeConformanceV5, screen } from 'test/utils';
4+
import Paper, { paperClasses } from '@material-ui/core/Paper';
5+
import Button from '@material-ui/core/Button';
6+
import MobileStepper, { mobileStepperClasses as classes } from '@material-ui/core/MobileStepper';
117
import KeyboardArrowRight from '../internal/svg-icons/KeyboardArrowRight';
12-
import Paper, { paperClasses } from '../Paper';
13-
import Button from '../Button/Button';
14-
import MobileStepper from './MobileStepper';
8+
import KeyboardArrowLeft from '../internal/svg-icons/KeyboardArrowLeft';
159

1610
describe('<MobileStepper />', () => {
1711
const mount = createMount();
1812
const render = createClientRender();
19-
let classes;
2013
const defaultProps = {
2114
steps: 2,
2215
nextButton: (
@@ -33,16 +26,17 @@ describe('<MobileStepper />', () => {
3326
),
3427
};
3528

36-
before(() => {
37-
classes = getClasses(<MobileStepper {...defaultProps} />);
38-
});
39-
40-
describeConformance(<MobileStepper {...defaultProps} />, () => ({
29+
describeConformanceV5(<MobileStepper {...defaultProps} />, () => ({
4130
classes,
4231
inheritComponent: Paper,
4332
mount,
33+
render,
34+
muiName: 'MuiMobileStepper',
35+
testVariantProps: { variant: 'progress' },
36+
testDeepOverrides: { slotName: 'dot', slotClassName: classes.dot },
37+
testStateOverrides: { prop: 'position', value: 'static', styleKey: 'positionStatic' },
4438
refInstanceof: window.HTMLDivElement,
45-
skip: ['componentProp'],
39+
skip: ['componentProp', 'componentsProp'],
4640
}));
4741

4842
it('should render a Paper with 0 elevation', () => {
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
export { default } from './MobileStepper';
22
export * from './MobileStepper';
3+
4+
export { default as mobileStepperClasses } from './mobileStepperClasses';
5+
export * from './mobileStepperClasses';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
export { default } from './MobileStepper';
2+
3+
export { default as mobileStepperClasses } from './mobileStepperClasses';
4+
export * from './mobileStepperClasses';
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { MobileStepperClassKey } from './MobileStepper';
2+
3+
declare const mobileStepperClasses: Record<MobileStepperClassKey, string>;
4+
5+
export function getMobileStepperUtilityClass(slot: string): string;
6+
7+
export default mobileStepperClasses;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled';
2+
3+
export function getMobileStepperUtilityClass(slot) {
4+
return generateUtilityClass('MuiMobileStepper', slot);
5+
}
6+
7+
const mobileStepperClasses = generateUtilityClasses('MuiMobileStepper', [
8+
'root',
9+
'positionBottom',
10+
'positionTop',
11+
'positionStatic',
12+
'dots',
13+
'dot',
14+
'dotActive',
15+
'progress',
16+
]);
17+
18+
export default mobileStepperClasses;

0 commit comments

Comments
 (0)