Skip to content

Commit

Permalink
[Stepper] Migrate MobileStepper to emotion (#25589)
Browse files Browse the repository at this point in the history
  • Loading branch information
natac13 authored Apr 6, 2021
1 parent d2e0076 commit 0327bb3
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 61 deletions.
3 changes: 2 additions & 1 deletion docs/pages/api-docs/mobile-stepper.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"default": "'bottom'"
},
"sx": { "type": { "name": "object" } },
"variant": {
"type": {
"name": "enum",
Expand Down Expand Up @@ -41,6 +42,6 @@
"filename": "/packages/material-ui/src/MobileStepper/MobileStepper.js",
"inheritance": { "component": "Paper", "pathname": "/api/paper/" },
"demos": "<ul><li><a href=\"/components/steppers/\">Steppers</a></li></ul>",
"styledComponent": false,
"styledComponent": true,
"cssComponent": false
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"nextButton": "A next button element. For instance, it can be a <code>Button</code> or an <code>IconButton</code>.",
"position": "Set the positioning type.",
"steps": "The total steps.",
"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.",
"variant": "The variant to use."
},
"classDescriptions": {
Expand Down
7 changes: 6 additions & 1 deletion packages/material-ui/src/MobileStepper/MobileStepper.d.ts
Original file line number Diff line number Diff line change
@@ -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 { PaperProps } from '../Paper';
import { LinearProgressProps } from '../LinearProgress';

Expand Down Expand Up @@ -52,6 +53,10 @@ export interface MobileStepperProps extends StandardProps<PaperProps, 'children'
* The total steps.
*/
steps: number;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
/**
* The variant to use.
* @default 'dots'
Expand Down
157 changes: 116 additions & 41 deletions packages/material-ui/src/MobileStepper/MobileStepper.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,101 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import { integerPropType } from '@material-ui/utils';
import withStyles from '../styles/withStyles';
import { integerPropType, deepmerge } from '@material-ui/utils';
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
import Paper from '../Paper';
import capitalize from '../utils/capitalize';
import LinearProgress from '../LinearProgress';

export const styles = (theme) => ({
/* Styles applied to the root element. */
root: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
background: theme.palette.background.default,
padding: 8,
import useThemeProps from '../styles/useThemeProps';
import experimentalStyled from '../styles/experimentalStyled';
import mobileStepperClasses, { getMobileStepperUtilityClass } from './mobileStepperClasses';

const overridesResolver = (props, styles) => {
const { styleProps } = props;

return deepmerge(
{
...styles[`position${capitalize(styleProps.position)}`],
[`& .${mobileStepperClasses.dots}`]: styles.dots,
[`& .${mobileStepperClasses.dot}`]: {
...styles.dot,
...(styleProps.dotActive && styles.dotActive),
},
[`& .${mobileStepperClasses.dotActive}`]: styles.dotActive,
[`& .${mobileStepperClasses.progress}`]: styles.progress,
},
styles.root || {},
);
};

const useUtilityClasses = (styleProps) => {
const { classes, position } = styleProps;

const slots = {
root: ['root', `position${capitalize(position)}`],
dots: ['dots'],
dot: ['dot'],
dotActive: ['dotActive'],
progress: ['progress'],
};

return composeClasses(slots, getMobileStepperUtilityClass, classes);
};

const MobileStepperRoot = experimentalStyled(
Paper,
{},
{
name: 'MuiMobileStepper',
slot: 'Root',
overridesResolver,
},
)(({ theme, styleProps }) => ({
/* Styles applied to the root element. */
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
background: theme.palette.background.default,
padding: 8,
/* Styles applied to the root element if `position="bottom"`. */
positionBottom: {
...(styleProps.position === 'bottom' && {
position: 'fixed',
bottom: 0,
left: 0,
right: 0,
zIndex: theme.zIndex.mobileStepper,
},
}),
/* Styles applied to the root element if `position="top"`. */
positionTop: {
...(styleProps.position === 'top' && {
position: 'fixed',
top: 0,
left: 0,
right: 0,
zIndex: theme.zIndex.mobileStepper,
},
/* Styles applied to the root element if `position="static"`. */
positionStatic: {},
}),
}));

const MobileStepperDots = experimentalStyled(
'div',
{},
{ name: 'MuiMobileStepper', slot: 'Dots' },
)(({ styleProps }) => ({
/* Styles applied to the dots container if `variant="dots"`. */
dots: {
...(styleProps.variant === 'dots' && {
display: 'flex',
flexDirection: 'row',
},
}),
}));

const MobileStepperDot = experimentalStyled(
'div',
{},
{ name: 'MuiMobileStepper', slot: 'Dot' },
)(({ theme, styleProps }) => ({
/* Styles applied to each dot if `variant="dots"`. */
dot: {
...(styleProps.variant === 'dots' && {
transition: theme.transitions.create('background-color', {
duration: theme.transitions.duration.shortest,
}),
Expand All @@ -50,22 +104,29 @@ export const styles = (theme) => ({
width: 8,
height: 8,
margin: '0 2px',
},
/* Styles applied to a dot if `variant="dots"` and this is the active step. */
dotActive: {
backgroundColor: theme.palette.primary.main,
},
/* Styles applied to a dot if `variant="dots"` and this is the active step. */
...(styleProps.dotActive && {
backgroundColor: theme.palette.primary.main,
}),
}),
}));

const MobileStepperProgress = experimentalStyled(
LinearProgress,
{},
{ name: 'MuiMobileStepper', slot: 'Progress' },
)(({ styleProps }) => ({
/* Styles applied to the Linear Progress component if `variant="progress"`. */
progress: {
...(styleProps.variant === 'progress' && {
width: '50%',
},
});
}),
}));

const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
const MobileStepper = React.forwardRef(function MobileStepper(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiMobileStepper' });
const {
activeStep = 0,
backButton,
classes,
className,
LinearProgressProps,
nextButton,
Expand All @@ -75,12 +136,22 @@ const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
...other
} = props;

const styleProps = {
...props,
activeStep,
position,
variant,
};

const classes = useUtilityClasses(styleProps);

return (
<Paper
<MobileStepperRoot
square
elevation={0}
className={clsx(classes.root, classes[`position${capitalize(position)}`], className)}
className={clsx(classes.root, className)}
ref={ref}
styleProps={styleProps}
{...other}
>
{backButton}
Expand All @@ -91,20 +162,20 @@ const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
)}

{variant === 'dots' && (
<div className={classes.dots}>
<MobileStepperDots styleProps={styleProps} className={classes.dots}>
{[...new Array(steps)].map((_, index) => (
<div
<MobileStepperDot
key={index}
className={clsx(classes.dot, {
[classes.dotActive]: index === activeStep,
})}
className={clsx(classes.dot, { [classes.dotActive]: index === activeStep })}
styleProps={{ ...styleProps, dotActive: index === activeStep }}
/>
))}
</div>
</MobileStepperDots>
)}

{variant === 'progress' && (
<LinearProgress
<MobileStepperProgress
styleProps={styleProps}
className={classes.progress}
variant="determinate"
value={Math.ceil((activeStep / (steps - 1)) * 100)}
Expand All @@ -113,7 +184,7 @@ const MobileStepper = React.forwardRef(function MobileStepper(props, ref) {
)}

{nextButton}
</Paper>
</MobileStepperRoot>
);
});

Expand Down Expand Up @@ -157,11 +228,15 @@ MobileStepper.propTypes /* remove-proptypes */ = {
* The total steps.
*/
steps: integerPropType.isRequired,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.object,
/**
* The variant to use.
* @default 'dots'
*/
variant: PropTypes.oneOf(['dots', 'progress', 'text']),
};

export default withStyles(styles, { name: 'MuiMobileStepper' })(MobileStepper);
export default MobileStepper;
30 changes: 12 additions & 18 deletions packages/material-ui/src/MobileStepper/MobileStepper.test.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import * as React from 'react';
import { expect } from 'chai';
import {
getClasses,
createMount,
createClientRender,
describeConformance,
screen,
} from 'test/utils';
import KeyboardArrowLeft from '../internal/svg-icons/KeyboardArrowLeft';
import { createMount, createClientRender, describeConformanceV5, screen } from 'test/utils';
import Paper, { paperClasses } from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button';
import MobileStepper, { mobileStepperClasses as classes } from '@material-ui/core/MobileStepper';
import KeyboardArrowRight from '../internal/svg-icons/KeyboardArrowRight';
import Paper, { paperClasses } from '../Paper';
import Button from '../Button/Button';
import MobileStepper from './MobileStepper';
import KeyboardArrowLeft from '../internal/svg-icons/KeyboardArrowLeft';

describe('<MobileStepper />', () => {
const mount = createMount();
const render = createClientRender();
let classes;
const defaultProps = {
steps: 2,
nextButton: (
Expand All @@ -33,16 +26,17 @@ describe('<MobileStepper />', () => {
),
};

before(() => {
classes = getClasses(<MobileStepper {...defaultProps} />);
});

describeConformance(<MobileStepper {...defaultProps} />, () => ({
describeConformanceV5(<MobileStepper {...defaultProps} />, () => ({
classes,
inheritComponent: Paper,
mount,
render,
muiName: 'MuiMobileStepper',
testVariantProps: { variant: 'progress' },
testDeepOverrides: { slotName: 'dot', slotClassName: classes.dot },
testStateOverrides: { prop: 'position', value: 'static', styleKey: 'positionStatic' },
refInstanceof: window.HTMLDivElement,
skip: ['componentProp'],
skip: ['componentProp', 'componentsProp'],
}));

it('should render a Paper with 0 elevation', () => {
Expand Down
3 changes: 3 additions & 0 deletions packages/material-ui/src/MobileStepper/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export { default } from './MobileStepper';
export * from './MobileStepper';

export { default as mobileStepperClasses } from './mobileStepperClasses';
export * from './mobileStepperClasses';
3 changes: 3 additions & 0 deletions packages/material-ui/src/MobileStepper/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export { default } from './MobileStepper';

export { default as mobileStepperClasses } from './mobileStepperClasses';
export * from './mobileStepperClasses';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { MobileStepperClassKey } from './MobileStepper';

declare const mobileStepperClasses: Record<MobileStepperClassKey, string>;

export function getMobileStepperUtilityClass(slot: string): string;

export default mobileStepperClasses;
18 changes: 18 additions & 0 deletions packages/material-ui/src/MobileStepper/mobileStepperClasses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { generateUtilityClass, generateUtilityClasses } from '@material-ui/unstyled';

export function getMobileStepperUtilityClass(slot) {
return generateUtilityClass('MuiMobileStepper', slot);
}

const mobileStepperClasses = generateUtilityClasses('MuiMobileStepper', [
'root',
'positionBottom',
'positionTop',
'positionStatic',
'dots',
'dot',
'dotActive',
'progress',
]);

export default mobileStepperClasses;

0 comments on commit 0327bb3

Please sign in to comment.