Skip to content

Commit

Permalink
[CircularProgress] Backport simplified determinate style & deprecate …
Browse files Browse the repository at this point in the history
…static (#22094)

Co-authored-by: Marija Najdova <mnajdova@gmail.com>
Co-authored-by: Olivier Tassinari <olivier.tassinari@gmail.com>
  • Loading branch information
3 people committed Aug 13, 2020
1 parent 1d351a8 commit 70aaac4
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 48 deletions.
4 changes: 3 additions & 1 deletion docs/pages/api-docs/circular-progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ The `MuiCircularProgress` name can be used for providing [default props](/custom
| <span class="prop-name">disableShrink</span> | <span class="prop-type">bool</span> | <span class="prop-default">false</span> | If `true`, the shrink animation is disabled. This only works if variant is `indeterminate`. |
| <span class="prop-name">size</span> | <span class="prop-type">number<br>&#124;&nbsp;string</span> | <span class="prop-default">40</span> | The size of the circle. If using a number, the pixel unit is assumed. If using a string, you need to provide the CSS unit, e.g '3rem'. |
| <span class="prop-name">thickness</span> | <span class="prop-type">number</span> | <span class="prop-default">3.6</span> | The thickness of the circle. |
| <span class="prop-name">value</span> | <span class="prop-type">number</span> | <span class="prop-default">0</span> | The value of the progress indicator for the determinate and static variants. Value between 0 and 100. |
| <span class="prop-name">value</span> | <span class="prop-type">number</span> | <span class="prop-default">0</span> | The value of the progress indicator for the determinate variant. Value between 0 and 100. |
| <span class="prop-name">variant</span> | <span class="prop-type">'determinate'<br>&#124;&nbsp;'indeterminate'<br>&#124;&nbsp;'static'</span> | <span class="prop-default">'indeterminate'</span> | The variant to use. Use indeterminate when there is no progress value. |

The `ref` is forwarded to the root element.
Expand All @@ -51,12 +51,14 @@ Any other props supplied will be provided to the root element (native element).
| <span class="prop-name">root</span> | <span class="prop-name">.MuiCircularProgress-root</span> | Styles applied to the root element.
| <span class="prop-name">static</span> | <span class="prop-name">.MuiCircularProgress-static</span> | Styles applied to the root element if `variant="static"`.
| <span class="prop-name">indeterminate</span> | <span class="prop-name">.MuiCircularProgress-indeterminate</span> | Styles applied to the root element if `variant="indeterminate"`.
| <span class="prop-name">determinate</span> | <span class="prop-name">.MuiCircularProgress-determinate</span> | Styles applied to the root element if `variant="determinate"`.
| <span class="prop-name">colorPrimary</span> | <span class="prop-name">.MuiCircularProgress-colorPrimary</span> | Styles applied to the root element if `color="primary"`.
| <span class="prop-name">colorSecondary</span> | <span class="prop-name">.MuiCircularProgress-colorSecondary</span> | Styles applied to the root element if `color="secondary"`.
| <span class="prop-name">svg</span> | <span class="prop-name">.MuiCircularProgress-svg</span> | Styles applied to the `svg` element.
| <span class="prop-name">circle</span> | <span class="prop-name">.MuiCircularProgress-circle</span> | Styles applied to the `circle` svg path.
| <span class="prop-name">circleStatic</span> | <span class="prop-name">.MuiCircularProgress-circleStatic</span> | Styles applied to the `circle` svg path if `variant="static"`.
| <span class="prop-name">circleIndeterminate</span> | <span class="prop-name">.MuiCircularProgress-circleIndeterminate</span> | Styles applied to the `circle` svg path if `variant="indeterminate"`.
| <span class="prop-name">circleDeterminate</span> | <span class="prop-name">.MuiCircularProgress-circleDeterminate</span> | Styles applied to the `circle` svg path if `variant="determinate"`.
| <span class="prop-name">circleDisableShrink</span> | <span class="prop-name">.MuiCircularProgress-circleDisableShrink</span> | Styles applied to the `circle` svg path if `disableShrink={true}`.

You can override the style of the component thanks to one of these customization points:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const useStyles = makeStyles((theme) => ({
},
}));

export default function CircularStatic() {
export default function CircularDeterminate() {
const classes = useStyles();
const [progress, setProgress] = React.useState(0);

Expand All @@ -27,11 +27,11 @@ export default function CircularStatic() {

return (
<div className={classes.root}>
<CircularProgress variant="static" value={25} />
<CircularProgress variant="static" value={50} />
<CircularProgress variant="static" value={75} />
<CircularProgress variant="static" value={100} />
<CircularProgress variant="static" value={progress} />
<CircularProgress variant="determinate" value={25} />
<CircularProgress variant="determinate" value={50} />
<CircularProgress variant="determinate" value={75} />
<CircularProgress variant="determinate" value={100} />
<CircularProgress variant="determinate" value={progress} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const useStyles = makeStyles((theme: Theme) =>
}),
);

export default function CircularStatic() {
export default function CircularDeterminate() {
const classes = useStyles();
const [progress, setProgress] = React.useState(0);

Expand All @@ -29,11 +29,11 @@ export default function CircularStatic() {

return (
<div className={classes.root}>
<CircularProgress variant="static" value={25} />
<CircularProgress variant="static" value={50} />
<CircularProgress variant="static" value={75} />
<CircularProgress variant="static" value={100} />
<CircularProgress variant="static" value={progress} />
<CircularProgress variant="determinate" value={25} />
<CircularProgress variant="determinate" value={50} />
<CircularProgress variant="determinate" value={75} />
<CircularProgress variant="determinate" value={100} />
<CircularProgress variant="determinate" value={progress} />
</div>
);
}
6 changes: 3 additions & 3 deletions docs/src/pages/components/progress/CircularWithValueLabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Box from '@material-ui/core/Box';
function CircularProgressWithLabel(props) {
return (
<Box position="relative" display="inline-flex">
<CircularProgress variant="static" {...props} />
<CircularProgress variant="determinate" {...props} />
<Box
top={0}
left={0}
Expand All @@ -28,7 +28,7 @@ function CircularProgressWithLabel(props) {

CircularProgressWithLabel.propTypes = {
/**
* The value of the progress indicator for the determinate and static variants.
* The value of the progress indicator for the determinate variant.
* Value between 0 and 100.
*/
value: PropTypes.number.isRequired,
Expand All @@ -39,7 +39,7 @@ export default function CircularStatic() {

React.useEffect(() => {
const timer = setInterval(() => {
setProgress((prevProgress) => (prevProgress >= 100 ? 10 : prevProgress + 10));
setProgress((prevProgress) => (prevProgress >= 100 ? 0 : prevProgress + 10));
}, 800);
return () => {
clearInterval(timer);
Expand Down
4 changes: 2 additions & 2 deletions docs/src/pages/components/progress/CircularWithValueLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Box from '@material-ui/core/Box';
function CircularProgressWithLabel(props: CircularProgressProps & { value: number }) {
return (
<Box position="relative" display="inline-flex">
<CircularProgress variant="static" {...props} />
<CircularProgress variant="determinate" {...props} />
<Box
top={0}
left={0}
Expand All @@ -30,7 +30,7 @@ export default function CircularStatic() {

React.useEffect(() => {
const timer = setInterval(() => {
setProgress((prevProgress) => (prevProgress >= 100 ? 10 : prevProgress + 10));
setProgress((prevProgress) => (prevProgress >= 100 ? 0 : prevProgress + 10));
}, 800);
return () => {
clearInterval(timer);
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/components/progress/progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ When displaying progress for a sequence of processes, indicate overall progress

### Circular determinate

{{"demo": "pages/components/progress/CircularStatic.js"}}
{{"demo": "pages/components/progress/CircularDeterminate.js"}}

### Interactive integration

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface CircularProgressProps
*/
thickness?: number;
/**
* The value of the progress indicator for the determinate and static variants.
* The value of the progress indicator for the determinate variant.
* Value between 0 and 100.
*/
value?: number;
Expand All @@ -41,12 +41,14 @@ export interface CircularProgressProps
export type CircularProgressClassKey =
| 'root'
| 'static'
| 'determinate'
| 'indeterminate'
| 'colorPrimary'
| 'colorSecondary'
| 'svg'
| 'circle'
| 'circleStatic'
| 'circleDeterminate'
| 'circleIndeterminate'
| 'circleDisableShrink';

Expand Down
51 changes: 24 additions & 27 deletions packages/material-ui/src/CircularProgress/CircularProgress.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,6 @@ import capitalize from '../utils/capitalize';

const SIZE = 44;

function getRelativeValue(value, min, max) {
return (Math.min(Math.max(min, value), max) - min) / (max - min);
}

function easeOut(t) {
t = getRelativeValue(t, 0, 1);
// https://gist.github.com/gre/1650294
t = (t -= 1) * t * t + 1;
return t;
}

function easeIn(t) {
return t * t;
}

export const styles = (theme) => ({
/* Styles applied to the root element. */
root: {
Expand All @@ -35,6 +20,10 @@ export const styles = (theme) => ({
indeterminate: {
animation: '$circular-rotate 1.4s linear infinite',
},
/* Styles applied to the root element if `variant="determinate"`. */
determinate: {
transition: theme.transitions.create('transform'),
},
/* Styles applied to the root element if `color="primary"`. */
colorPrimary: {
color: theme.palette.primary.main,
Expand Down Expand Up @@ -64,6 +53,10 @@ export const styles = (theme) => ({
strokeDasharray: '80px, 200px',
strokeDashoffset: '0px', // Add the unit to fix a Edge 16 and below bug.
},
/* Styles applied to the `circle` svg path if `variant="determinate"`. */
circleDeterminate: {
transition: theme.transitions.create('stroke-dashoffset'),
},
'@keyframes circular-rotate': {
'0%': {
// Fix IE 11 wobbly
Expand Down Expand Up @@ -122,16 +115,8 @@ const CircularProgress = React.forwardRef(function CircularProgress(props, ref)
const circumference = 2 * Math.PI * ((SIZE - thickness) / 2);
circleStyle.strokeDasharray = circumference.toFixed(3);
rootProps['aria-valuenow'] = Math.round(value);

if (variant === 'static') {
circleStyle.strokeDashoffset = `${(((100 - value) / 100) * circumference).toFixed(3)}px`;
rootStyle.transform = 'rotate(-90deg)';
} else {
circleStyle.strokeDashoffset = `${(easeIn((100 - value) / 100) * circumference).toFixed(
3,
)}px`;
rootStyle.transform = `rotate(${(easeOut(value / 70) * 270).toFixed(3)}deg)`;
}
circleStyle.strokeDashoffset = `${(((100 - value) / 100) * circumference).toFixed(3)}px`;
rootStyle.transform = 'rotate(-90deg)';
}

return (
Expand All @@ -140,6 +125,7 @@ const CircularProgress = React.forwardRef(function CircularProgress(props, ref)
classes.root,
{
[classes[`color${capitalize(color)}`]]: color !== 'inherit',
[classes.determinate]: variant === 'determinate',
[classes.indeterminate]: variant === 'indeterminate',
[classes.static]: variant === 'static',
},
Expand All @@ -154,6 +140,7 @@ const CircularProgress = React.forwardRef(function CircularProgress(props, ref)
<svg className={classes.svg} viewBox={`${SIZE / 2} ${SIZE / 2} ${SIZE} ${SIZE}`}>
<circle
className={clsx(classes.circle, {
[classes.circleDeterminate]: variant === 'determinate',
[classes.circleIndeterminate]: variant === 'indeterminate',
[classes.circleStatic]: variant === 'static',
[classes.circleDisableShrink]: disableShrink,
Expand Down Expand Up @@ -217,15 +204,25 @@ CircularProgress.propTypes = {
*/
thickness: PropTypes.number,
/**
* The value of the progress indicator for the determinate and static variants.
* The value of the progress indicator for the determinate variant.
* Value between 0 and 100.
*/
value: PropTypes.number,
/**
* The variant to use.
* Use indeterminate when there is no progress value.
*/
variant: PropTypes.oneOf(['determinate', 'indeterminate', 'static']),
variant: chainPropTypes(PropTypes.oneOf(['determinate', 'indeterminate', 'static']), (props) => {
const { variant } = props;

if (variant === 'static') {
throw new Error(
'Material-UI: `variant="static"` was deprecated. Use `variant="determinate"` instead.',
);
}

return null;
}),
};

export default withStyles(styles, { name: 'MuiCircularProgress', flip: false })(CircularProgress);
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { expect } from 'chai';
import { stub } from 'sinon';
import { createClientRender } from 'test/utils/createClientRender';
import { getClasses } from '@material-ui/core/test-utils';
import createMount from 'test/utils/createMount';
Expand Down Expand Up @@ -77,6 +79,15 @@ describe('<CircularProgress />', () => {
});

describe('prop: variant="static', () => {
beforeEach(() => {
PropTypes.resetWarningCache();
stub(console, 'error');
});

afterEach(() => {
console.error.restore();
});

it('should set strokeDasharray of circle', () => {
const { container } = render(<CircularProgress variant="static" value={70} />);
const circularProgress = container.firstChild;
Expand All @@ -93,6 +104,22 @@ describe('<CircularProgress />', () => {
);
expect(circularProgress).to.have.attribute('aria-valuenow', '70');
});

it('issues a warning for variant="static"', () => {
PropTypes.checkPropTypes(
CircularProgress.Naked.propTypes,
{
variant: 'static',
},
'props',
'Avatar',
);

expect(console.error.callCount).to.equal(1);
expect(console.error.firstCall.args[0]).to.equal(
'Warning: Failed props type: Material-UI: `variant="static"` was deprecated. Use `variant="determinate"` instead.',
);
});
});

describe('prop: variant="determinate"', () => {
Expand All @@ -119,7 +146,7 @@ describe('<CircularProgress />', () => {
'should have strokeDasharray set',
);
expect(circle.style.strokeDashoffset).to.equal(
'11.423px',
'38.076px',
'should have strokeDashoffset set',
);
expect(circularProgress).to.have.attribute('aria-valuenow', '70');
Expand Down

0 comments on commit 70aaac4

Please sign in to comment.