diff --git a/docs/data/material/migration/upgrade-to-v7/migrating-from-deprecated-apis.md b/docs/data/material/migration/upgrade-to-v7/migrating-from-deprecated-apis.md
new file mode 100644
index 00000000000000..4e32fbb8a87a0f
--- /dev/null
+++ b/docs/data/material/migration/upgrade-to-v7/migrating-from-deprecated-apis.md
@@ -0,0 +1,69 @@
+# Migrating from deprecated APIs
+
+
Learn how to migrate away from recently deprecated APIs before they become breaking changes.
+
+## Why you should migrate
+
+Features become deprecated over time as maintainers make improvements to the APIs.
+Migrating to these improved APIs results in a better developer experience, so it's in your best interest to stay up to date.
+Deprecated APIs often become breaking changes in subsequent major versions, so the sooner you migrate, the smoother the next major update will be.
+
+## Autocomplete
+
+Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#autocomplete-props) below to migrate the code as described in the following sections:
+
+```bash
+npx @mui/codemod@latest deprecations/autocomplete-props
+```
+
+### renderTags prop
+
+The `renderTags` prop is deprecated, use `renderValue` instead.
+
+```diff
+
+- value.map((option, index) => (
+-
+- ))
+- }
++ renderValue={(value, getItemProps, ownerState) =>
++ value.map((option, index) => (
++
++ ))
++ }
+ />
+```
+
+---
+
+### useAutocomplete deprecated fields
+
+The following return value fields are deprecated from the `useAutocomplete` hook:
+
+- `getTagProps` → use `getItemProps`
+- `focusedTag` → use `focusedItem`
+
+#### getTagProps
+
+```diff
+ const {
+- getTagProps,
++ getItemProps,
+ } = useAutocomplete(props);
+
+ // ...
+-
++
+```
+
+#### focusedTag
+
+```diff
+ const {
+- focusedTag,
++ focusedItem,
+ } = useAutocomplete(props);
+```
diff --git a/docs/data/material/migration/upgrade-to-v7/upgrade-to-v7.md b/docs/data/material/migration/upgrade-to-v7/upgrade-to-v7.md
index 4e60553eb7f55f..0a73e3d2f7e5ee 100644
--- a/docs/data/material/migration/upgrade-to-v7/upgrade-to-v7.md
+++ b/docs/data/material/migration/upgrade-to-v7/upgrade-to-v7.md
@@ -139,6 +139,13 @@ Material UI v7 uses `react-is@19`, which changed how React elements are identif
If you're on React 18 or below, mismatched versions of `react-is` can cause runtime errors in prop type checks.
Forcing `react-is` to match your React version prevents these errors.
+## Deprecations
+
+It is not required to immediately go through the deprecations in order to use Material UI v7.
+
+You can do it at your own pace by checking out the [deprecations page](/material-ui/migration/v7/migrating-from-deprecated-apis/).
+Those deprecations will be removed in the next major version.
+
## Breaking changes
Since v7 is a new major release, it contains some changes that affect the public API.
diff --git a/docs/data/material/pages.ts b/docs/data/material/pages.ts
index 339a0cedf6221d..f7d02ea8a5b6e9 100644
--- a/docs/data/material/pages.ts
+++ b/docs/data/material/pages.ts
@@ -317,6 +317,10 @@ const pages: MuiPage[] = [
pathname: '/material-ui/migration/upgrade-to-v7',
title: 'Upgrade to v7: getting started',
},
+ {
+ pathname: '/material-ui/migration/v7/migrating-from-deprecated-apis',
+ title: 'Migrating from deprecated APIs',
+ },
{
pathname: '/material-ui/migration/upgrade-to-native-color',
title: 'Native color',
diff --git a/docs/pages/material-ui/migration/v7/migrating-from-deprecated-apis.js b/docs/pages/material-ui/migration/v7/migrating-from-deprecated-apis.js
new file mode 100644
index 00000000000000..88f2104b5bd3b8
--- /dev/null
+++ b/docs/pages/material-ui/migration/v7/migrating-from-deprecated-apis.js
@@ -0,0 +1,6 @@
+import MarkdownDocs from 'docs/src/modules/components/MarkdownDocs';
+import * as pageProps from 'docs/data/material/migration/upgrade-to-v7/migrating-from-deprecated-apis.md?muiMarkdown';
+
+export default function Page() {
+ return ;
+}
diff --git a/docs/translations/translations.json b/docs/translations/translations.json
index f1f7b5f6ea016b..04e35f79d3d733 100644
--- a/docs/translations/translations.json
+++ b/docs/translations/translations.json
@@ -177,6 +177,7 @@
"/material-ui/migration/pickers-migration": "Migration from @material-ui/pickers",
"Upgrade to v7": "Upgrade to v7",
"/material-ui/migration/upgrade-to-v7": "Upgrade to v7: getting started",
+ "/material-ui/migration/v7/migrating-from-deprecated-apis": "Migrating from deprecated APIs",
"/material-ui/migration/upgrade-to-native-color": "Native color",
"Upgrade to v6": "Upgrade to v6",
"/material-ui/migration/upgrade-to-v6": "Upgrade to v6: getting started",
diff --git a/packages/mui-codemod/README.md b/packages/mui-codemod/README.md
index 0d36aa921a0ea8..26ee2754fffa01 100644
--- a/packages/mui-codemod/README.md
+++ b/packages/mui-codemod/README.md
@@ -278,6 +278,11 @@ npx @mui/codemod@latest deprecations/alert-props
- PopperComponent={CustomPopper}
- ListboxComponent={CustomListbox}
- ListboxProps={{ height: 12 }}
+- renderTags={(value, getTagProps, ownerState) =>
+- value.map((option, index) => (
+-
+- ))
+- }
- componentsProps={{
- clearIndicator: { width: 10 },
- paper: { width: 12 },
@@ -299,6 +304,11 @@ npx @mui/codemod@latest deprecations/alert-props
+ popper: { width: 14 },
+ popupIndicator: { width: 16 },
+ }}
++ renderValue={(value, getItemProps, ownerState) =>
++ value.map((option, index) => (
++
++ ))
++ }
/>
```
@@ -310,6 +320,10 @@ npx @mui/codemod@latest deprecations/alert-props
- PopperComponent: CustomPopper,
- ListboxComponent: CustomListbox,
- ListboxProps: { height: 12 },
+- renderTags: (value, getTagProps, ownerState) =>
+- value.map((option, index) => (
+-
+- )),
- componentsProps: {
- clearIndicator: { width: 10 },
- paper: { width: 12 },
@@ -331,10 +345,23 @@ npx @mui/codemod@latest deprecations/alert-props
+ popper: { width: 14 },
+ popupIndicator: { width: 16 },
+ },
++ renderValue: (value, getItemProps, ownerState) =>
++ value.map((option, index) => (
++
++ )),
},
},
```
+```diff
+ const {
+- getTagProps,
+- focusedTag,
++ getItemProps,
++ focusedItem,
+ } = useAutocomplete(props);
+```
+
```bash
npx @mui/codemod@latest deprecations/autocomplete-props
```
diff --git a/packages/mui-codemod/src/deprecations/autocomplete-props/autocomplete-props.js b/packages/mui-codemod/src/deprecations/autocomplete-props/autocomplete-props.js
index 5ec12ceb7c25ee..95fdd84eb5c4e3 100644
--- a/packages/mui-codemod/src/deprecations/autocomplete-props/autocomplete-props.js
+++ b/packages/mui-codemod/src/deprecations/autocomplete-props/autocomplete-props.js
@@ -6,6 +6,99 @@ import findComponentDefaultProps from '../../util/findComponentDefaultProps';
import assignObject from '../../util/assignObject';
import appendAttribute from '../../util/appendAttribute';
+function isNonComputedKey(j, path) {
+ const parent = path.parent.node;
+
+ return (
+ (j.ObjectProperty.check(parent) || j.Property.check(parent)) &&
+ parent.key === path.node &&
+ !parent.computed
+ );
+}
+
+function renameIdentifiersInScope(j, scopePath, oldName, newName) {
+ const bindingScope = scopePath.scope.lookup(oldName);
+
+ if (!bindingScope) {
+ return;
+ }
+
+ j(bindingScope.path)
+ .find(j.Identifier, { name: oldName })
+ .filter((path) => {
+ if (isNonComputedKey(j, path)) {
+ return false;
+ }
+
+ return path.scope.lookup(oldName) === bindingScope;
+ })
+ .replaceWith(() => j.identifier(newName));
+}
+
+function renameRenderTagsCallback(j, callbackPath) {
+ const getTagPropsParam = callbackPath.node.params[1];
+
+ if (getTagPropsParam?.type === 'Identifier' && getTagPropsParam.name === 'getTagProps') {
+ renameIdentifiersInScope(j, callbackPath, 'getTagProps', 'getItemProps');
+ }
+}
+
+function renameRenderTagsProp(j, propertyPath) {
+ if (propertyPath.node.key.type === 'Identifier') {
+ propertyPath.node.key.name = 'renderValue';
+ }
+
+ if (
+ propertyPath.node.value.type === 'ArrowFunctionExpression' ||
+ propertyPath.node.value.type === 'FunctionExpression'
+ ) {
+ renameRenderTagsCallback(j, propertyPath.get('value'));
+ }
+}
+
+function renameUseAutocompleteReturnMembers(j, root) {
+ const renamedMembers = new Map([
+ ['getTagProps', 'getItemProps'],
+ ['focusedTag', 'focusedItem'],
+ ]);
+
+ root
+ .find(j.VariableDeclarator)
+ .filter((path) => {
+ const { id, init } = path.node;
+
+ return (
+ id.type === 'ObjectPattern' &&
+ init?.type === 'CallExpression' &&
+ init.callee.type === 'Identifier' &&
+ init.callee.name === 'useAutocomplete'
+ );
+ })
+ .forEach((path) => {
+ path.node.id.properties.forEach((property) => {
+ if (property.type !== 'ObjectProperty' || property.key.type !== 'Identifier') {
+ return;
+ }
+
+ const nextName = renamedMembers.get(property.key.name);
+
+ if (!nextName) {
+ return;
+ }
+
+ const isShorthand = property.shorthand === true;
+ const localName = property.value.type === 'Identifier' ? property.value.name : null;
+
+ property.key.name = nextName;
+
+ if (isShorthand && localName) {
+ renameIdentifiersInScope(j, path, localName, nextName);
+ property.shorthand = true;
+ }
+ });
+ });
+}
+
/**
* @param {import('jscodeshift').FileInfo} file
* @param {import('jscodeshift').API} api
@@ -59,6 +152,26 @@ export default function transformer(file, api, options) {
{ root, packageName: options.packageName, componentName: 'Autocomplete' },
(elementPath) => {
const element = elementPath.node;
+
+ element.openingElement.attributes.forEach((attribute, index) => {
+ if (attribute.type !== 'JSXAttribute' || attribute.name.name !== 'renderTags') {
+ return;
+ }
+
+ attribute.name.name = 'renderValue';
+
+ if (
+ attribute.value?.type === 'JSXExpressionContainer' &&
+ (attribute.value.expression.type === 'ArrowFunctionExpression' ||
+ attribute.value.expression.type === 'FunctionExpression')
+ ) {
+ renameRenderTagsCallback(
+ j,
+ elementPath.get('openingElement', 'attributes', index, 'value', 'expression'),
+ );
+ }
+ });
+
const propIndex = element.openingElement.attributes.findIndex(
(attr) => attr.type === 'JSXAttribute' && attr.name.name === 'ListboxComponent',
);
@@ -169,5 +282,13 @@ export default function transformer(file, api, options) {
path.prune();
});
+ defaultPropsPathCollection
+ .find(j.ObjectProperty, { key: { name: 'renderTags' } })
+ .forEach((path) => {
+ renameRenderTagsProp(j, path);
+ });
+
+ renameUseAutocompleteReturnMembers(j, root);
+
return root.toSource(printOptions);
}
diff --git a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/actual.js b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/actual.js
index 76a939df4f9629..16f72231ca9b5b 100644
--- a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/actual.js
+++ b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/actual.js
@@ -1,5 +1,7 @@
import Autocomplete from '@mui/material/Autocomplete';
import {Autocomplete as MyAutocomplete} from '@mui/material';
+import Chip from '@mui/material/Chip';
+import useAutocomplete from '@mui/material/useAutocomplete';
+/>;
+
+
+ value.map((option, index) => (
+
+ ))
+ }
+/>;
+
+const { getTagProps, focusedTag } = useAutocomplete(props);
+
+;
+
+const { getTagProps: getAutocompleteTagProps, focusedTag: focusedAutocompleteTag } =
+ useAutocomplete(props);
+
+;
diff --git a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/expected.js b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/expected.js
index f18d47190402d5..eba5aef99dfe09 100644
--- a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/expected.js
+++ b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/expected.js
@@ -1,5 +1,7 @@
import Autocomplete from '@mui/material/Autocomplete';
import {Autocomplete as MyAutocomplete} from '@mui/material';
+import Chip from '@mui/material/Chip';
+import useAutocomplete from '@mui/material/useAutocomplete';
+/>;
+
+
+ value.map((option, index) => (
+
+ ))
+ }
+/>;
+
+const { getItemProps, focusedItem } = useAutocomplete(props);
+
+;
+
+const { getItemProps: getAutocompleteTagProps, focusedItem: focusedAutocompleteTag } =
+ useAutocomplete(props);
+
+;
diff --git a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.actual.js b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.actual.js
index 482b767c1e37e9..281b9706ce4747 100644
--- a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.actual.js
+++ b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.actual.js
@@ -1,5 +1,6 @@
import Autocomplete from '@org/ui/material/Autocomplete';
import {Autocomplete as MyAutocomplete} from '@org/ui/material';
+import Chip from '@org/ui/material/Chip';
;
+
+
+ value.map((option, index) => )
+ }
/>
diff --git a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.expected.js b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.expected.js
index 32da3ab85fd8b3..f6b88c26bd9d6f 100644
--- a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.expected.js
+++ b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/package.expected.js
@@ -1,5 +1,6 @@
import Autocomplete from '@org/ui/material/Autocomplete';
import {Autocomplete as MyAutocomplete} from '@org/ui/material';
+import Chip from '@org/ui/material/Chip';
;
+
+
+ value.map((option, index) => )
+ }
/>
diff --git a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.actual.js b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.actual.js
index 5b144b5440188b..09956b98a59946 100644
--- a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.actual.js
+++ b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.actual.js
@@ -6,6 +6,10 @@ fn({
PopperComponent: CustomPopper,
ListboxComponent: CustomListbox,
ListboxProps: { height: 12 },
+ renderTags: (value, getTagProps, ownerState) =>
+ value.map((option, index) => (
+
+ )),
componentsProps: {
clearIndicator: { width: 10 },
paper: { width: 12 },
@@ -24,6 +28,10 @@ fn({
PopperComponent: CustomPopper,
ListboxComponent: CustomListbox,
ListboxProps: { height: 12 },
+ renderTags: (value, getTagProps, ownerState) =>
+ value.map((option, index) => (
+
+ )),
slotProps: {
popupIndicator: { width: 20 }
},
diff --git a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.expected.js b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.expected.js
index 93e6dcda392428..92aa80250e147e 100644
--- a/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.expected.js
+++ b/packages/mui-codemod/src/deprecations/autocomplete-props/test-cases/theme.expected.js
@@ -1,6 +1,11 @@
fn({
MuiAutocomplete: {
defaultProps: {
+ renderValue: (value, getItemProps, ownerState) =>
+ value.map((option, index) => (
+
+ )),
+
slots: {
paper: CustomPaper,
popper: CustomPopper
@@ -25,6 +30,11 @@ fn({
fn({
MuiAutocomplete: {
defaultProps: {
+ renderValue: (value, getItemProps, ownerState) =>
+ value.map((option, index) => (
+
+ )),
+
slotProps: {
clearIndicator: { width: 10 },
paper: { width: 12 },