diff --git a/docs/data/material/components/menus/menus.md b/docs/data/material/components/menus/menus.md index f8b357ae77bdcc..0794be30c28999 100644 --- a/docs/data/material/components/menus/menus.md +++ b/docs/data/material/components/menus/menus.md @@ -17,13 +17,19 @@ A menu displays a list of choices on a temporary surface. It appears when the us {{"component": "@mui/docs/ComponentLinkHeader"}} +## Introduction + +Menus are implemented using a collection of related components: + +- Menu: The container/surface of the menu. +- Menu Item: An option for users to select from the menu. +- Menu List (optional): Alternative composable container for Menu Items—see [Composition with Menu List](#composition-with-menu-list) for details. + ## Basic menu A basic menu opens over the anchor element by default (this option can be [changed](#menu-positioning) via props). When close to a screen edge, a basic menu vertically realigns to make sure that all menu items are completely visible. -Choosing an option should immediately ideally commit the option and close the menu. - -**Disambiguation**: In contrast to simple menus, simple dialogs can present additional detail related to the options available for a list item or provide navigational or orthogonal actions related to the primary task. Although they can display the same content, simple menus are preferred over simple dialogs because simple menus are less disruptive to the user's current context. +You should configure the component so that selecting an option immediately confirms it and closes the menu, as shown in the demo below. {{"demo": "BasicMenu.js"}} @@ -54,13 +60,13 @@ For instance, you can display the menu on top of the anchor: {{"demo": "PositionedMenu.js"}} -## MenuList composition +## Composition with Menu List -The `Menu` component uses the `Popover` component internally. -However, you might want to use a different positioning strategy, or not blocking the scroll. -For answering those needs, we expose a `MenuList` component that you can compose, with `Popper` in this example. +The Menu component uses the Popover component internally. +But you might want to use a different positioning strategy, or prefer not to block scrolling, for example. -The primary responsibility of the `MenuList` component is to handle the focus. +The Menu List component lets you compose your own menu for these kinds of use cases—its primary purpose is to handle focus. +See the demo below for an example of composition that uses Menu List and replaces the Menu's default Popover with a Popper component instead: {{"demo": "MenuListComposition.js", "bg": true}} diff --git a/docs/data/material/components/popper/popper.md b/docs/data/material/components/popper/popper.md index 24c9dcb54c8423..1730cd0fd38c6e 100644 --- a/docs/data/material/components/popper/popper.md +++ b/docs/data/material/components/popper/popper.md @@ -20,7 +20,7 @@ Some important features of the Popper component: - The scroll isn't blocked like with the [Popover](/material-ui/react-popover/) component. The placement of the popper updates with the available area in the viewport. - Clicking away does not hide the Popper component. - If you need this behavior, you can use the [Base UI Click-Away Listener](/base-ui/react-click-away-listener/) - see the example in the [menu documentation section](/material-ui/react-menu/#menulist-composition). + If you need this behavior, you can use the [Base UI Click-Away Listener](/base-ui/react-click-away-listener/) - see the example in the [menu documentation section](/material-ui/react-menu/#composition-with-menu-list). - The `anchorEl` is passed as the reference object to create a new `Popper.js` instance. {{"component": "@mui/docs/ComponentLinkHeader", "design": false}} diff --git a/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md b/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md index 24c27c33051d02..bc806137a91255 100644 --- a/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md +++ b/docs/data/material/migration/migrating-from-deprecated-apis/migrating-from-deprecated-apis.md @@ -1375,6 +1375,70 @@ Here's how to migrate: }, ``` +## LinearProgress + +Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#linear-progress-classes) below to migrate the code as described in the following sections: + +```bash +npx @mui/codemod@latest deprecations/linear-progress-classes +``` + +### Composed CSS classes + +The CSS classes that composed the `variant` and `color` prop values were deprecated. + +Here's how to migrate: + +```diff +-.MuiLinearProgress-bar1Buffer ++.MuiLinearProgress-buffer > .MuiLinearProgress-bar1 +-.MuiLinearProgress-bar1Determinate ++.MuiLinearProgress-determinate > .MuiLinearProgress-bar1 +-.MuiLinearProgress-bar1Indeterminate ++.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar1 +-.MuiLinearProgress-bar2Buffer ++.MuiLinearProgress-buffer > .MuiLinearProgress-bar2 +-.MuiLinearProgress-bar2Indeterminate ++.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar2 +-.MuiLinearProgress-barColorPrimary ++.MuiLinearProgress-colorPrimary > .MuiLinearProgress-bar +-.MuiLinearProgress-barColorSecondary ++.MuiLinearProgress-colorSecondary > .MuiLinearProgress-bar +-.MuiLinearProgress-dashedColorPrimary ++.MuiLinearProgress-colorPrimary > .MuiLinearProgress-dashed +-.MuiLinearProgress-dashedColorSecondary ++.MuiLinearProgress-colorSecondary > .MuiLinearProgress-dashed +``` + +```diff + import { linearProgressClasses } from '@mui/material/LinearProgress'; + + MuiLinearProgress: { + styleOverrides: { + root: { +- [`&.${linearProgressClasses.bar1Buffer}`]: {}, ++ [`&.${linearProgressClasses.buffer} > .${linearProgressClasses.bar1}`]: {}, +- [`&.${linearProgressClasses.bar1Determinate}`]: {}, ++ [`&.${linearProgressClasses.determinate} > .${linearProgressClasses.bar1}`]: {}, +- [`&.${linearProgressClasses.bar1Indeterminate}`]: {}, ++ [`&.${linearProgressClasses.indeterminate} > .${linearProgressClasses.bar1}`]: {}, +- [`&.${linearProgressClasses.bar2Buffer}`]: {}, ++ [`&.${linearProgressClasses.buffer} > .${linearProgressClasses.bar2}`]: {}, +- [`&.${linearProgressClasses.bar2Indeterminate}`]: {}, ++ [`&.${linearProgressClasses.indeterminate} > .${linearProgressClasses.bar2}`]: {}, +- [`&.${linearProgressClasses.barColorPrimary}`]: {}, ++ [`&.${linearProgressClasses.colorPrimary} > .${linearProgressClasses.bar}`]: {}, +- [`&.${linearProgressClasses.barColorSecondary}`]: {}, ++ [`&.${linearProgressClasses.colorSecondary} > .${linearProgressClasses.bar}`]: {}, +- [`&.${linearProgressClasses.dashedColorPrimary}`]: {}, ++ [`&.${linearProgressClasses.colorPrimary} > .${linearProgressClasses.dashed}`]: {}, +- [`&.${linearProgressClasses.dashedColorSecondary}`]: {}, ++ [`&.${linearProgressClasses.colorSecondary} > .${linearProgressClasses.dashed}`]: {}, + }, + }, + } +``` + ## Modal Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#modal-props) below to migrate the code as described in the following sections: diff --git a/docs/pages/material-ui/api/linear-progress.json b/docs/pages/material-ui/api/linear-progress.json index f6118ba323228f..09371e65e408d3 100644 --- a/docs/pages/material-ui/api/linear-progress.json +++ b/docs/pages/material-ui/api/linear-progress.json @@ -37,47 +37,66 @@ "description": "Styles applied to the layered bar1 and bar2 elements.", "isGlobal": false }, + { + "key": "bar1", + "className": "MuiLinearProgress-bar1", + "description": "Styles applied to the bar1 element.", + "isGlobal": false + }, { "key": "bar1Buffer", "className": "MuiLinearProgress-bar1Buffer", "description": "Styles applied to the bar1 element if `variant=\"buffer\"`.", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "bar1Determinate", "className": "MuiLinearProgress-bar1Determinate", "description": "Styles applied to the bar1 element if `variant=\"determinate\"`.", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "bar1Indeterminate", "className": "MuiLinearProgress-bar1Indeterminate", "description": "Styles applied to the bar1 element if `variant=\"indeterminate or query\"`.", + "isGlobal": false, + "isDeprecated": true + }, + { + "key": "bar2", + "className": "MuiLinearProgress-bar2", + "description": "Styles applied to the bar2 element.", "isGlobal": false }, { "key": "bar2Buffer", "className": "MuiLinearProgress-bar2Buffer", "description": "Styles applied to the bar2 element if `variant=\"buffer\"`.", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "bar2Indeterminate", "className": "MuiLinearProgress-bar2Indeterminate", "description": "Styles applied to the bar2 element if `variant=\"indeterminate or query\"`.", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "barColorPrimary", "className": "MuiLinearProgress-barColorPrimary", "description": "Styles applied to the bar elements if `color=\"primary\"`; bar2 if `variant` not \"buffer\".", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "barColorSecondary", "className": "MuiLinearProgress-barColorSecondary", "description": "Styles applied to the bar elements if `color=\"secondary\"`; bar2 if `variant` not \"buffer\".", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "buffer", @@ -107,13 +126,15 @@ "key": "dashedColorPrimary", "className": "MuiLinearProgress-dashedColorPrimary", "description": "Styles applied to the additional bar element if `variant=\"buffer\"` and `color=\"primary\"`.", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "dashedColorSecondary", "className": "MuiLinearProgress-dashedColorSecondary", "description": "Styles applied to the additional bar element if `variant=\"buffer\"` and `color=\"secondary\"`.", - "isGlobal": false + "isGlobal": false, + "isDeprecated": true }, { "key": "determinate", diff --git a/docs/translations/api-docs/linear-progress/linear-progress.json b/docs/translations/api-docs/linear-progress/linear-progress.json index 832be0ad1151f0..697fe047053067 100644 --- a/docs/translations/api-docs/linear-progress/linear-progress.json +++ b/docs/translations/api-docs/linear-progress/linear-progress.json @@ -21,40 +21,49 @@ "description": "Styles applied to {{nodeName}}.", "nodeName": "the layered bar1 and bar2 elements" }, + "bar1": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the bar1 element" }, "bar1Buffer": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the bar1 element", - "conditions": "variant=\"buffer\"" + "conditions": "variant=\"buffer\"", + "deprecationInfo": "Use the .MuiLinearProgress-bar1 and .MuiLinearProgress-buffer classes instead. How to migrate" }, "bar1Determinate": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the bar1 element", - "conditions": "variant=\"determinate\"" + "conditions": "variant=\"determinate\"", + "deprecationInfo": "Use the .MuiLinearProgress-bar1 and .MuiLinearProgress-determinate classes instead. How to migrate" }, "bar1Indeterminate": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the bar1 element", - "conditions": "variant=\"indeterminate or query\"" + "conditions": "variant=\"indeterminate or query\"", + "deprecationInfo": "Use the .MuiLinearProgress-bar1 and .MuiLinearProgress-indeterminate classes instead. How to migrate" }, + "bar2": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the bar2 element" }, "bar2Buffer": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the bar2 element", - "conditions": "variant=\"buffer\"" + "conditions": "variant=\"buffer\"", + "deprecationInfo": "Use the .MuiLinearProgress-bar2 and .MuiLinearProgress-buffer classes instead. How to migrate" }, "bar2Indeterminate": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the bar2 element", - "conditions": "variant=\"indeterminate or query\"" + "conditions": "variant=\"indeterminate or query\"", + "deprecationInfo": "Use the .MuiLinearProgress-bar2 and .MuiLinearProgress-indeterminate classes instead. How to migrate" }, "barColorPrimary": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the bar elements", - "conditions": "color=\"primary\"; bar2 if variant not "buffer"" + "conditions": "color=\"primary\"; bar2 if variant not "buffer"", + "deprecationInfo": "Use the .MuiLinearProgress-bar and .MuiLinearProgress-colorPrimary classes instead. How to migrate" }, "barColorSecondary": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the bar elements", - "conditions": "color=\"secondary\"; bar2 if variant not "buffer"" + "conditions": "color=\"secondary\"; bar2 if variant not "buffer"", + "deprecationInfo": "Use the .MuiLinearProgress-bar and .MuiLinearProgress-colorSecondary classes instead. How to migrate" }, "buffer": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", @@ -79,12 +88,14 @@ "dashedColorPrimary": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the additional bar element", - "conditions": "variant=\"buffer\" and color=\"primary\"" + "conditions": "variant=\"buffer\" and color=\"primary\"", + "deprecationInfo": "Combine the .MuiLinearProgress-dashed and .MuiLinearProgress-colorPrimary classes instead. How to migrate" }, "dashedColorSecondary": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the additional bar element", - "conditions": "variant=\"buffer\" and color=\"secondary\"" + "conditions": "variant=\"buffer\" and color=\"secondary\"", + "deprecationInfo": "Combine the .MuiLinearProgress-dashed and .MuiLinearProgress-colorSecondary classes instead. How to migrate" }, "determinate": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", diff --git a/packages/mui-codemod/README.md b/packages/mui-codemod/README.md index aa51cb7a8373c2..d376805bb85e80 100644 --- a/packages/mui-codemod/README.md +++ b/packages/mui-codemod/README.md @@ -1242,6 +1242,66 @@ npx @mui/codemod@latest deprecations/input-base-props npx @mui/codemod@latest deprecations/input-props ``` +#### `linear-progress-classes` + +JS transforms: + +```diff + import { linearProgressClasses } from '@mui/material/LinearProgress'; + + MuiLinearProgress: { + styleOverrides: { + root: { +- [`&.${linearProgressClasses.bar1Buffer}`]: {}, ++ [`&.${linearProgressClasses.buffer} > .${linearProgressClasses.bar1}`]: {}, +- [`&.${linearProgressClasses.bar1Determinate}`]: {}, ++ [`&.${linearProgressClasses.determinate} > .${linearProgressClasses.bar1}`]: {}, +- [`&.${linearProgressClasses.bar1Indeterminate}`]: {}, ++ [`&.${linearProgressClasses.indeterminate} > .${linearProgressClasses.bar1}`]: {}, +- [`&.${linearProgressClasses.bar2Buffer}`]: {}, ++ [`&.${linearProgressClasses.buffer} > .${linearProgressClasses.bar2}`]: {}, +- [`&.${linearProgressClasses.bar2Indeterminate}`]: {}, ++ [`&.${linearProgressClasses.indeterminate} > .${linearProgressClasses.bar2}`]: {}, +- [`&.${linearProgressClasses.barColorPrimary}`]: {}, ++ [`&.${linearProgressClasses.colorPrimary} > .${linearProgressClasses.bar}`]: {}, +- [`&.${linearProgressClasses.barColorSecondary}`]: {}, ++ [`&.${linearProgressClasses.colorSecondary} > .${linearProgressClasses.bar}`]: {}, +- [`&.${linearProgressClasses.dashedColorPrimary}`]: {}, ++ [`&.${linearProgressClasses.colorPrimary} > .${linearProgressClasses.dashed}`]: {}, +- [`&.${linearProgressClasses.dashedColorSecondary}`]: {}, ++ [`&.${linearProgressClasses.colorSecondary} > .${linearProgressClasses.dashed}`]: {}, + }, + }, + } +``` + +CSS transforms: + +```diff +-.MuiLinearProgress-bar1Buffer ++.MuiLinearProgress-buffer > .MuiLinearProgress-bar1 +-.MuiLinearProgress-bar1Determinate ++.MuiLinearProgress-determinate > .MuiLinearProgress-bar1 +-.MuiLinearProgress-bar1Indeterminate ++.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar1 +-.MuiLinearProgress-bar2Buffer ++.MuiLinearProgress-buffer > .MuiLinearProgress-bar2 +-.MuiLinearProgress-bar2Indeterminate ++.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar2 +-.MuiLinearProgress-barColorPrimary ++.MuiLinearProgress-colorPrimary > .MuiLinearProgress-bar +-.MuiLinearProgress-barColorSecondary ++.MuiLinearProgress-colorSecondary > .MuiLinearProgress-bar +-.MuiLinearProgress-dashedColorPrimary ++.MuiLinearProgress-colorPrimary > .MuiLinearProgress-dashed +-.MuiLinearProgress-dashedColorSecondary ++.MuiLinearProgress-colorSecondary > .MuiLinearProgress-dashed +``` + +```bash +npx @mui/codemod@latest deprecations/linear-progress-classes +``` + #### `modal-props` ```diff diff --git a/packages/mui-codemod/src/deprecations/all/deprecations-all.js b/packages/mui-codemod/src/deprecations/all/deprecations-all.js index 08306a961d8891..80a7f5138b9a68 100644 --- a/packages/mui-codemod/src/deprecations/all/deprecations-all.js +++ b/packages/mui-codemod/src/deprecations/all/deprecations-all.js @@ -16,6 +16,7 @@ import transformImageListItemBarClasses from '../image-list-item-bar-classes'; import transformInputBaseProps from '../input-base-props'; import transformInputProps from '../input-props'; import transformListItemTextProps from '../list-item-text-props'; +import transformLinearProgressClasses from '../linear-progress-classes'; import transformModalProps from '../modal-props'; import transformOutlinedInputProps from '../outlined-input-props'; import transformPaginationItemClasses from '../pagination-item-classes'; @@ -54,6 +55,7 @@ export default function deprecationsAll(file, api, options) { file.source = transformInputBaseProps(file, api, options); file.source = transformInputProps(file, api, options); file.source = transformListItemTextProps(file, api, options); + file.source = transformLinearProgressClasses(file, api, options); file.source = transformModalProps(file, api, options); file.source = transformOutlinedInputProps(file, api, options); file.source = transformPaginationItemClasses(file, api, options); diff --git a/packages/mui-codemod/src/deprecations/all/postcss.config.js b/packages/mui-codemod/src/deprecations/all/postcss.config.js index 948f51a315bae8..2ec94017b76d05 100644 --- a/packages/mui-codemod/src/deprecations/all/postcss.config.js +++ b/packages/mui-codemod/src/deprecations/all/postcss.config.js @@ -15,6 +15,9 @@ const { const { plugin: circularProgressClassesPlugin, } = require('../circular-progress-classes/postcss-plugin'); +const { + plugin: linearProgressClassesPlugin, +} = require('../linear-progress-classes/postcss-plugin'); const { plugin: tabClassesPlugin } = require('../tab-classes/postcss-plugin'); const { plugin: tableSortLabelClassesPlugin, @@ -29,6 +32,7 @@ module.exports = { buttonGroupClassesPlugin, chipClassesPlugin, circularProgressClassesPlugin, + linearProgressClassesPlugin, paginationItemClassesPlugin, stepConnectorClassesPlugin, toggleButtonGroupClassesPlugin, diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/index.js b/packages/mui-codemod/src/deprecations/linear-progress-classes/index.js new file mode 100644 index 00000000000000..07c2d8f1caca3d --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/index.js @@ -0,0 +1 @@ +export { default } from './linear-progress-classes'; diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/linear-progress-classes.js b/packages/mui-codemod/src/deprecations/linear-progress-classes/linear-progress-classes.js new file mode 100644 index 00000000000000..dbe1241401791b --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/linear-progress-classes.js @@ -0,0 +1,129 @@ +import { classes } from './postcss-plugin'; + +/** + * @param {import('jscodeshift').FileInfo} file + * @param {import('jscodeshift').API} api + */ +export default function transformer(file, api, options) { + const j = api.jscodeshift; + const root = j(file.source); + + const printOptions = options.printOptions; + classes.forEach(({ deprecatedClass, replacementSelector }) => { + const replacementSelectorPrefix = '&'; + root + .find(j.ImportDeclaration) + .filter((path) => path.node.source.value.match(/^@mui\/material\/LinearProgress$/)) + .forEach((path) => { + path.node.specifiers.forEach((specifier) => { + if ( + specifier.type === 'ImportSpecifier' && + specifier.imported.name === 'linearProgressClasses' + ) { + const deprecatedAtomicClass = deprecatedClass.replace( + `${deprecatedClass.split('-')[0]}-`, + '', + ); + + root + .find(j.MemberExpression, { + object: { name: specifier.local.name }, + property: { name: deprecatedAtomicClass }, + }) + .forEach((memberExpression) => { + const parent = memberExpression.parentPath.parentPath.value; + if (parent.type === j.TemplateLiteral.name) { + const memberExpressionIndex = parent.expressions.findIndex( + (expression) => expression === memberExpression.value, + ); + const precedingTemplateElement = parent.quasis[memberExpressionIndex]; + const atomicClasses = replacementSelector + .replaceAll('MuiLinearProgress-', '') + .replaceAll(replacementSelectorPrefix, '') + .replaceAll(' > ', '') + .split('.') + .filter(Boolean); + + if ( + precedingTemplateElement.value.raw.endsWith( + deprecatedClass.startsWith(' ') + ? `${replacementSelectorPrefix} .` + : `${replacementSelectorPrefix}.`, + ) + ) { + const atomicClassesArgs = [ + memberExpressionIndex, + 1, + ...atomicClasses.map((atomicClass) => + j.memberExpression( + memberExpression.value.object, + j.identifier(atomicClass), + ), + ), + ]; + parent.expressions.splice(...atomicClassesArgs); + + if (replacementSelector.includes(' > ')) { + const quasisArgs = [ + memberExpressionIndex, + 1, + j.templateElement( + { + raw: precedingTemplateElement.value.raw.replace(' ', ''), + cooked: precedingTemplateElement.value.cooked.replace(' ', ''), + }, + false, + ), + j.templateElement({ raw: ' > .', cooked: ' > .' }, false), + ]; + + if (atomicClasses.length === 3) { + quasisArgs.splice( + 3, + 0, + j.templateElement({ raw: '.', cooked: '.' }, false), + ); + } + + parent.quasis.splice(...quasisArgs); + } else { + parent.quasis.splice( + memberExpressionIndex, + 1, + j.templateElement( + { + raw: precedingTemplateElement.value.raw, + cooked: precedingTemplateElement.value.cooked, + }, + false, + ), + + j.templateElement({ raw: '.', cooked: '.' }, false), + ); + } + } + } + }); + } + }); + }); + + const selectorRegex = new RegExp(`^${replacementSelectorPrefix}${deprecatedClass}`); + root + .find( + j.Literal, + (literal) => typeof literal.value === 'string' && literal.value.match(selectorRegex), + ) + .forEach((path) => { + path.replace( + j.literal( + path.value.value.replace( + selectorRegex, + `${replacementSelectorPrefix}${replacementSelector}`, + ), + ), + ); + }); + }); + return root.toSource(printOptions); +} diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/linear-progress-classes.test.js b/packages/mui-codemod/src/deprecations/linear-progress-classes/linear-progress-classes.test.js new file mode 100644 index 00000000000000..fbad32e703a40c --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/linear-progress-classes.test.js @@ -0,0 +1,79 @@ +import path from 'path'; +import { expect } from 'chai'; +import postcss from 'postcss'; +import { jscodeshift } from '../../../testUtils'; +import jsTransform from './linear-progress-classes'; +import { plugin as postcssPlugin } from './postcss-plugin'; +import readFile from '../../util/readFile'; + +function read(fileName) { + return readFile(path.join(__dirname, fileName)); +} + +const postcssProcessor = postcss([postcssPlugin]); + +describe('@mui/codemod', () => { + describe('deprecations', () => { + describe('linear-progress-classes', () => { + describe('js-transform', () => { + it('transforms props as needed', () => { + const actual = jsTransform( + { source: read('./test-cases/actual.js') }, + { jscodeshift }, + { printOptions: { quote: 'single', trailingComma: true } }, + ); + + const expected = read('./test-cases/expected.js'); + + expect(actual).to.equal(expected, 'The transformed version should be correct'); + }); + + it('should be idempotent', () => { + const actual = jsTransform( + { source: read('./test-cases/expected.js') }, + { jscodeshift }, + {}, + ); + + const expected = read('./test-cases/expected.js'); + expect(actual).to.equal(expected, 'The transformed version should be correct'); + }); + }); + + describe('css-transform', () => { + it('transforms classes as needed', async () => { + const actual = await postcssProcessor.process(read('./test-cases/actual.css'), { + from: undefined, + }); + + const expected = read('./test-cases/expected.css'); + expect(actual.css).to.equal(expected, 'The transformed version should be correct'); + }); + + it('should be idempotent', async () => { + const actual = await postcssProcessor.process(read('./test-cases/expected.css'), { + from: undefined, + }); + + const expected = read('./test-cases/expected.css'); + expect(actual.css).to.equal(expected, 'The transformed version should be correct'); + }); + }); + + describe('test-cases', () => { + it('should not be the same', () => { + const actualJS = read('./test-cases/actual.js'); + const expectedJS = read('./test-cases/expected.js'); + expect(actualJS).not.to.equal(expectedJS, 'The actual and expected should be different'); + + const actualCSS = read('./test-cases/actual.css'); + const expectedCSS = read('./test-cases/expected.css'); + expect(actualCSS).not.to.equal( + expectedCSS, + 'The actual and expected should be different', + ); + }); + }); + }); + }); +}); diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/postcss-plugin.js b/packages/mui-codemod/src/deprecations/linear-progress-classes/postcss-plugin.js new file mode 100644 index 00000000000000..e0e452efcc64ca --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/postcss-plugin.js @@ -0,0 +1,61 @@ +const classes = [ + { + deprecatedClass: ' .MuiLinearProgress-bar1Buffer', + replacementSelector: '.MuiLinearProgress-buffer > .MuiLinearProgress-bar1', + }, + { + deprecatedClass: ' .MuiLinearProgress-bar1Determinate', + replacementSelector: '.MuiLinearProgress-determinate > .MuiLinearProgress-bar1', + }, + { + deprecatedClass: ' .MuiLinearProgress-bar1Indeterminate', + replacementSelector: '.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar1', + }, + { + deprecatedClass: ' .MuiLinearProgress-bar2Buffer', + replacementSelector: '.MuiLinearProgress-buffer > .MuiLinearProgress-bar2', + }, + { + deprecatedClass: ' .MuiLinearProgress-bar2Indeterminate', + replacementSelector: '.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar2', + }, + { + deprecatedClass: ' .MuiLinearProgress-barColorPrimary', + replacementSelector: '.MuiLinearProgress-colorPrimary > .MuiLinearProgress-bar', + }, + { + deprecatedClass: ' .MuiLinearProgress-barColorSecondary', + replacementSelector: '.MuiLinearProgress-colorSecondary > .MuiLinearProgress-bar', + }, + { + deprecatedClass: ' .MuiLinearProgress-dashedColorPrimary', + replacementSelector: '.MuiLinearProgress-colorPrimary > .MuiLinearProgress-dashed', + }, + { + deprecatedClass: ' .MuiLinearProgress-dashedColorSecondary', + replacementSelector: '.MuiLinearProgress-colorSecondary > .MuiLinearProgress-dashed', + }, +]; + +const plugin = () => { + return { + postcssPlugin: `Replace deprecated LinearProgress classes with new classes`, + Rule(rule) { + const { selector } = rule; + + classes.forEach(({ deprecatedClass, replacementSelector }) => { + const selectorRegex = new RegExp(`${deprecatedClass}`); + + if (selector.match(selectorRegex)) { + rule.selector = selector.replace(selectorRegex, replacementSelector); + } + }); + }, + }; +}; +plugin.postcss = true; + +module.exports = { + plugin, + classes, +}; diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/postcss.config.js b/packages/mui-codemod/src/deprecations/linear-progress-classes/postcss.config.js new file mode 100644 index 00000000000000..23bebc1125be6e --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/postcss.config.js @@ -0,0 +1,5 @@ +const { plugin } = require('./postcss-plugin'); + +module.exports = { + plugins: [plugin], +}; diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/actual.css b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/actual.css new file mode 100644 index 00000000000000..d48b26ef322745 --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/actual.css @@ -0,0 +1,35 @@ +.MuiLinearProgress-root .MuiLinearProgress-bar1Buffer { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-bar1Determinate { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-bar1Indeterminate { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-bar2Buffer { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-bar2Indeterminate { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-barColorPrimary { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-barColorSecondary { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-dashedColorPrimary { + color: red; +} + +.MuiLinearProgress-root .MuiLinearProgress-dashedColorSecondary { + color: red; +} diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/actual.js b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/actual.js new file mode 100644 index 00000000000000..0952821bf7eb10 --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/actual.js @@ -0,0 +1,20 @@ +import { linearProgressClasses } from '@mui/material/LinearProgress'; + +('& .MuiLinearProgress-bar1Buffer'); +('& .MuiLinearProgress-bar1Determinate'); +('& .MuiLinearProgress-bar1Indeterminate'); +('& .MuiLinearProgress-bar2Buffer'); +('& .MuiLinearProgress-bar2Indeterminate'); +('& .MuiLinearProgress-barColorPrimary'); +('& .MuiLinearProgress-barColorSecondary'); +('& .MuiLinearProgress-dashedColorPrimary'); +('& .MuiLinearProgress-dashedColorSecondary'); +`& .${linearProgressClasses.bar1Buffer}`; +`& .${linearProgressClasses.bar1Determinate}`; +`& .${linearProgressClasses.bar1Indeterminate}`; +`& .${linearProgressClasses.bar2Buffer}`; +`& .${linearProgressClasses.bar2Indeterminate}`; +`& .${linearProgressClasses.barColorPrimary}`; +`& .${linearProgressClasses.barColorSecondary}`; +`& .${linearProgressClasses.dashedColorPrimary}`; +`& .${linearProgressClasses.dashedColorSecondary}`; diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/expected.css b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/expected.css new file mode 100644 index 00000000000000..8bdd1f598da790 --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/expected.css @@ -0,0 +1,35 @@ +.MuiLinearProgress-root.MuiLinearProgress-buffer > .MuiLinearProgress-bar1 { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-determinate > .MuiLinearProgress-bar1 { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar1 { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-buffer > .MuiLinearProgress-bar2 { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar2 { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-colorPrimary > .MuiLinearProgress-bar { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-colorSecondary > .MuiLinearProgress-bar { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-colorPrimary > .MuiLinearProgress-dashed { + color: red; +} + +.MuiLinearProgress-root.MuiLinearProgress-colorSecondary > .MuiLinearProgress-dashed { + color: red; +} diff --git a/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/expected.js b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/expected.js new file mode 100644 index 00000000000000..38385104f60c9b --- /dev/null +++ b/packages/mui-codemod/src/deprecations/linear-progress-classes/test-cases/expected.js @@ -0,0 +1,20 @@ +import { linearProgressClasses } from '@mui/material/LinearProgress'; + +('&.MuiLinearProgress-buffer > .MuiLinearProgress-bar1'); +('&.MuiLinearProgress-determinate > .MuiLinearProgress-bar1'); +('&.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar1'); +('&.MuiLinearProgress-buffer > .MuiLinearProgress-bar2'); +('&.MuiLinearProgress-indeterminate > .MuiLinearProgress-bar2'); +('&.MuiLinearProgress-colorPrimary > .MuiLinearProgress-bar'); +('&.MuiLinearProgress-colorSecondary > .MuiLinearProgress-bar'); +('&.MuiLinearProgress-colorPrimary > .MuiLinearProgress-dashed'); +('&.MuiLinearProgress-colorSecondary > .MuiLinearProgress-dashed'); +`&.${linearProgressClasses.buffer} > .${linearProgressClasses.bar1}`; +`&.${linearProgressClasses.determinate} > .${linearProgressClasses.bar1}`; +`&.${linearProgressClasses.indeterminate} > .${linearProgressClasses.bar1}`; +`&.${linearProgressClasses.buffer} > .${linearProgressClasses.bar2}`; +`&.${linearProgressClasses.indeterminate} > .${linearProgressClasses.bar2}`; +`&.${linearProgressClasses.colorPrimary} > .${linearProgressClasses.bar}`; +`&.${linearProgressClasses.colorSecondary} > .${linearProgressClasses.bar}`; +`&.${linearProgressClasses.colorPrimary} > .${linearProgressClasses.dashed}`; +`&.${linearProgressClasses.colorSecondary} > .${linearProgressClasses.dashed}`; diff --git a/packages/mui-material/src/LinearProgress/LinearProgress.js b/packages/mui-material/src/LinearProgress/LinearProgress.js index 9046d1e69dbe38..0e327bd11ed5c3 100644 --- a/packages/mui-material/src/LinearProgress/LinearProgress.js +++ b/packages/mui-material/src/LinearProgress/LinearProgress.js @@ -94,6 +94,7 @@ const useUtilityClasses = (ownerState) => { dashed: ['dashed', `dashedColor${capitalize(color)}`], bar1: [ 'bar', + 'bar1', `barColor${capitalize(color)}`, (variant === 'indeterminate' || variant === 'query') && 'bar1Indeterminate', variant === 'determinate' && 'bar1Determinate', @@ -101,6 +102,7 @@ const useUtilityClasses = (ownerState) => { ], bar2: [ 'bar', + 'bar2', variant !== 'buffer' && `barColor${capitalize(color)}`, variant === 'buffer' && `color${capitalize(color)}`, (variant === 'indeterminate' || variant === 'query') && 'bar2Indeterminate', @@ -231,6 +233,7 @@ const LinearProgressBar1 = styled('span', { return [ styles.bar, + styles.bar1, styles[`barColor${capitalize(ownerState.color)}`], (ownerState.variant === 'indeterminate' || ownerState.variant === 'query') && styles.bar1Indeterminate, @@ -307,6 +310,7 @@ const LinearProgressBar2 = styled('span', { return [ styles.bar, + styles.bar2, styles[`barColor${capitalize(ownerState.color)}`], (ownerState.variant === 'indeterminate' || ownerState.variant === 'query') && styles.bar2Indeterminate, diff --git a/packages/mui-material/src/LinearProgress/LinearProgress.test.js b/packages/mui-material/src/LinearProgress/LinearProgress.test.js index 5a97ff6fc1b88e..647ac9549c971f 100644 --- a/packages/mui-material/src/LinearProgress/LinearProgress.test.js +++ b/packages/mui-material/src/LinearProgress/LinearProgress.test.js @@ -30,6 +30,8 @@ describe('', () => { expect(progressbar).to.have.class(classes.indeterminate); expect(progressbar.children[0]).to.have.class(classes.bar1Indeterminate); expect(progressbar.children[1]).to.have.class(classes.bar2Indeterminate); + expect(progressbar.children[0]).to.have.class(classes.bar1); + expect(progressbar.children[1]).to.have.class(classes.bar2); }); it('should render for the primary color by default', () => { diff --git a/packages/mui-material/src/LinearProgress/linearProgressClasses.ts b/packages/mui-material/src/LinearProgress/linearProgressClasses.ts index 37590edad59c67..48da9927f277ad 100644 --- a/packages/mui-material/src/LinearProgress/linearProgressClasses.ts +++ b/packages/mui-material/src/LinearProgress/linearProgressClasses.ts @@ -18,25 +18,47 @@ export interface LinearProgressClasses { query: string; /** Styles applied to the additional bar element if `variant="buffer"`. */ dashed: string; - /** Styles applied to the additional bar element if `variant="buffer"` and `color="primary"`. */ + /** Styles applied to the additional bar element if `variant="buffer"` and `color="primary"`. + * @deprecated Combine the [.MuiLinearProgress-dashed](/material-ui/api/linear-progress/#linear-progress-classes-dashed) and [.MuiLinearProgress-colorPrimary](/material-ui/api/linear-progress/#linear-progress-classes-colorPrimary) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ dashedColorPrimary: string; - /** Styles applied to the additional bar element if `variant="buffer"` and `color="secondary"`. */ + /** Styles applied to the additional bar element if `variant="buffer"` and `color="secondary"`. + * @deprecated Combine the [.MuiLinearProgress-dashed](/material-ui/api/linear-progress/#linear-progress-classes-dashed) and [.MuiLinearProgress-colorSecondary](/material-ui/api/linear-progress/#linear-progress-classes-colorSecondary) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ dashedColorSecondary: string; /** Styles applied to the layered bar1 and bar2 elements. */ bar: string; - /** Styles applied to the bar elements if `color="primary"`; bar2 if `variant` not "buffer". */ + /** Styles applied to the bar1 element. */ + bar1: string; + /** Styles applied to the bar2 element. */ + bar2: string; + /** Styles applied to the bar elements if `color="primary"`; bar2 if `variant` not "buffer". + * @deprecated Use the [.MuiLinearProgress-bar](/material-ui/api/linear-progress/#linear-progress-classes-bar) and [.MuiLinearProgress-colorPrimary](/material-ui/api/linear-progress/#linear-progress-classes-colorPrimary) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ barColorPrimary: string; - /** Styles applied to the bar elements if `color="secondary"`; bar2 if `variant` not "buffer". */ + /** Styles applied to the bar elements if `color="secondary"`; bar2 if `variant` not "buffer". + * @deprecated Use the [.MuiLinearProgress-bar](/material-ui/api/linear-progress/#linear-progress-classes-bar) and [.MuiLinearProgress-colorSecondary](/material-ui/api/linear-progress/#linear-progress-classes-colorSecondary) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ barColorSecondary: string; - /** Styles applied to the bar1 element if `variant="indeterminate or query"`. */ + /** Styles applied to the bar1 element if `variant="indeterminate or query"`. + * @deprecated Use the [.MuiLinearProgress-bar1](/material-ui/api/linear-progress/#linear-progress-classes-bar1) and [.MuiLinearProgress-indeterminate](/material-ui/api/linear-progress/#linear-progress-classes-indeterminate) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ bar1Indeterminate: string; - /** Styles applied to the bar1 element if `variant="determinate"`. */ + /** Styles applied to the bar1 element if `variant="determinate"`. + * @deprecated Use the [.MuiLinearProgress-bar1](/material-ui/api/linear-progress/#linear-progress-classes-bar1) and [.MuiLinearProgress-determinate](/material-ui/api/linear-progress/#linear-progress-classes-determinate) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ bar1Determinate: string; - /** Styles applied to the bar1 element if `variant="buffer"`. */ + /** Styles applied to the bar1 element if `variant="buffer"`. + * @deprecated Use the [.MuiLinearProgress-bar1](/material-ui/api/linear-progress/#linear-progress-classes-bar1) and [.MuiLinearProgress-buffer](/material-ui/api/linear-progress/#linear-progress-classes-buffer) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ bar1Buffer: string; - /** Styles applied to the bar2 element if `variant="indeterminate or query"`. */ + /** Styles applied to the bar2 element if `variant="indeterminate or query"`. + * @deprecated Use the [.MuiLinearProgress-bar2](/material-ui/api/linear-progress/#linear-progress-classes-bar2) and [.MuiLinearProgress-indeterminate](/material-ui/api/linear-progress/#linear-progress-classes-indeterminate) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ bar2Indeterminate: string; - /** Styles applied to the bar2 element if `variant="buffer"`. */ + /** Styles applied to the bar2 element if `variant="buffer"`. + * @deprecated Use the [.MuiLinearProgress-bar2](/material-ui/api/linear-progress/#linear-progress-classes-bar2) and [.MuiLinearProgress-buffer](/material-ui/api/linear-progress/#linear-progress-classes-buffer) classes instead. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) + */ bar2Buffer: string; } @@ -58,6 +80,8 @@ const linearProgressClasses: LinearProgressClasses = generateUtilityClasses('Mui 'dashedColorPrimary', 'dashedColorSecondary', 'bar', + 'bar1', + 'bar2', 'barColorPrimary', 'barColorSecondary', 'bar1Indeterminate',