From 7ad889323e6afcadf9da53c0f64e86a1807a05c7 Mon Sep 17 00:00:00 2001 From: Gavin-10 <81329254+Gavin-10@users.noreply.github.com> Date: Thu, 14 Nov 2024 07:46:40 -0500 Subject: [PATCH 01/14] [material-ui][Button] Add loading feature to Button and IconButton (#42987) --- .../button-group/LoadingButtonGroup.js | 7 +- .../button-group/LoadingButtonGroup.tsx | 7 +- .../LoadingButtonGroup.tsx.preview | 6 +- .../components/button-group/button-group.md | 8 +- .../components/buttons/IconButtonWithBadge.js | 37 ++ .../buttons/IconButtonWithBadge.tsx | 37 ++ .../buttons/IconButtonWithBadge.tsx.preview | 9 + .../components/buttons/LoadingButtons.js | 42 +- .../components/buttons/LoadingButtons.tsx | 42 +- .../buttons/LoadingButtons.tsx.preview | 14 - .../buttons/LoadingButtonsTransition.js | 39 +- .../buttons/LoadingButtonsTransition.tsx | 39 +- .../components/buttons/LoadingIconButton.js | 21 + .../components/buttons/LoadingIconButton.tsx | 21 + .../buttons/LoadingIconButton.tsx.preview | 5 + .../material/components/buttons/buttons.md | 36 +- .../dialogs/ToolpadDialogsNoSnap.js | 9 +- .../dialogs/ToolpadDialogsNoSnap.tsx | 9 +- .../migration/upgrade-to-v6/upgrade-to-v6.md | 16 +- docs/data/material/pagesApi.js | 1 - docs/pages/blog/2020-q2-update.md | 2 +- docs/pages/blog/mui-core-v5.md | 2 +- docs/pages/material-ui/api/button.json | 54 +++ docs/pages/material-ui/api/icon-button.json | 17 + docs/pages/material-ui/api/loading-button.js | 23 - .../pages/material-ui/api/loading-button.json | 453 ------------------ docs/src/pagesApi.js | 1 - docs/translations/api-docs/button/button.json | 43 ++ .../api-docs/icon-button/icon-button.json | 15 + .../loading-button/loading-button.json | 356 -------------- .../src/LoadingButton/LoadingButton.d.ts | 82 +--- .../src/LoadingButton/LoadingButton.js | 363 +------------- .../src/LoadingButton/LoadingButton.spec.tsx | 16 - .../src/LoadingButton/LoadingButton.test.js | 117 ----- packages/mui-lab/src/LoadingButton/index.d.ts | 3 - packages/mui-lab/src/LoadingButton/index.js | 3 - .../src/LoadingButton/loadingButtonClasses.ts | 43 -- packages/mui-material/src/Button/Button.d.ts | 17 + packages/mui-material/src/Button/Button.js | 222 ++++++++- .../mui-material/src/Button/Button.spec.tsx | 14 + .../mui-material/src/Button/Button.test.js | 44 +- .../mui-material/src/Button/buttonClasses.ts | 21 + .../src/IconButton/IconButton.d.ts | 12 + .../mui-material/src/IconButton/IconButton.js | 57 ++- .../src/IconButton/IconButton.test.js | 44 +- .../src/IconButton/iconButtonClasses.ts | 6 + .../Button/FullWidthLoadingButtons.js | 14 +- 47 files changed, 862 insertions(+), 1587 deletions(-) create mode 100644 docs/data/material/components/buttons/IconButtonWithBadge.js create mode 100644 docs/data/material/components/buttons/IconButtonWithBadge.tsx create mode 100644 docs/data/material/components/buttons/IconButtonWithBadge.tsx.preview delete mode 100644 docs/data/material/components/buttons/LoadingButtons.tsx.preview create mode 100644 docs/data/material/components/buttons/LoadingIconButton.js create mode 100644 docs/data/material/components/buttons/LoadingIconButton.tsx create mode 100644 docs/data/material/components/buttons/LoadingIconButton.tsx.preview delete mode 100644 docs/pages/material-ui/api/loading-button.js delete mode 100644 docs/pages/material-ui/api/loading-button.json delete mode 100644 docs/translations/api-docs/loading-button/loading-button.json delete mode 100644 packages/mui-lab/src/LoadingButton/LoadingButton.spec.tsx delete mode 100644 packages/mui-lab/src/LoadingButton/LoadingButton.test.js delete mode 100644 packages/mui-lab/src/LoadingButton/loadingButtonClasses.ts diff --git a/docs/data/material/components/button-group/LoadingButtonGroup.js b/docs/data/material/components/button-group/LoadingButtonGroup.js index 989f028daf7a56..fd146a90620d10 100644 --- a/docs/data/material/components/button-group/LoadingButtonGroup.js +++ b/docs/data/material/components/button-group/LoadingButtonGroup.js @@ -1,17 +1,16 @@ import * as React from 'react'; import ButtonGroup from '@mui/material/ButtonGroup'; import Button from '@mui/material/Button'; -import LoadingButton from '@mui/lab/LoadingButton'; import SaveIcon from '@mui/icons-material/Save'; export default function LoadingButtonGroup() { return ( - Fetch data - }> + + ); } diff --git a/docs/data/material/components/button-group/LoadingButtonGroup.tsx b/docs/data/material/components/button-group/LoadingButtonGroup.tsx index 989f028daf7a56..fd146a90620d10 100644 --- a/docs/data/material/components/button-group/LoadingButtonGroup.tsx +++ b/docs/data/material/components/button-group/LoadingButtonGroup.tsx @@ -1,17 +1,16 @@ import * as React from 'react'; import ButtonGroup from '@mui/material/ButtonGroup'; import Button from '@mui/material/Button'; -import LoadingButton from '@mui/lab/LoadingButton'; import SaveIcon from '@mui/icons-material/Save'; export default function LoadingButtonGroup() { return ( - Fetch data - }> + + ); } diff --git a/docs/data/material/components/button-group/LoadingButtonGroup.tsx.preview b/docs/data/material/components/button-group/LoadingButtonGroup.tsx.preview index 51360c91557385..a69903f1fca35c 100644 --- a/docs/data/material/components/button-group/LoadingButtonGroup.tsx.preview +++ b/docs/data/material/components/button-group/LoadingButtonGroup.tsx.preview @@ -1,7 +1,7 @@ - Fetch data - }> + + \ No newline at end of file diff --git a/docs/data/material/components/button-group/button-group.md b/docs/data/material/components/button-group/button-group.md index 6cc23f74925aec..5bceb0b6ab282b 100644 --- a/docs/data/material/components/button-group/button-group.md +++ b/docs/data/material/components/button-group/button-group.md @@ -1,7 +1,7 @@ --- productId: material-ui title: React Button Group component -components: Button, ButtonGroup, LoadingButton +components: Button, ButtonGroup githubLabel: 'component: ButtonGroup' githubSource: packages/mui-material/src/ButtonGroup --- @@ -49,10 +49,8 @@ You can remove the elevation with the `disableElevation` prop. {{"demo": "DisableElevation.js"}} -## Experimental APIs +## Loading -### Loading button - -You can use the [``](/material-ui/react-button/#loading-button) from [`@mui/lab`](/material-ui/about-the-lab/) in the button group. +Use the `loading` prop from `Button` to set buttons in a loading state and disable interactions. {{"demo": "LoadingButtonGroup.js"}} diff --git a/docs/data/material/components/buttons/IconButtonWithBadge.js b/docs/data/material/components/buttons/IconButtonWithBadge.js new file mode 100644 index 00000000000000..6a00cbd44b6180 --- /dev/null +++ b/docs/data/material/components/buttons/IconButtonWithBadge.js @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { styled } from '@mui/material/styles'; +import IconButton from '@mui/material/IconButton'; +import Badge, { badgeClasses } from '@mui/material/Badge'; +import Stack from '@mui/material/Stack'; +import SaveIcon from '@mui/icons-material/Save'; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCartOutlined'; + +const CartBadge = styled(Badge)` + .${badgeClasses.badge} { + top: -12px; + right: -6px; + } +`; + +export default function IconButtonWithBadge() { + const [loading, setLoading] = React.useState(false); + React.useEffect(() => { + const timeout = setTimeout(() => { + setLoading(false); + }, 2000); + return () => clearTimeout(timeout); + }); + return ( + + + + + + + setLoading(true)}> + + + + + ); +} diff --git a/docs/data/material/components/buttons/IconButtonWithBadge.tsx b/docs/data/material/components/buttons/IconButtonWithBadge.tsx new file mode 100644 index 00000000000000..6a00cbd44b6180 --- /dev/null +++ b/docs/data/material/components/buttons/IconButtonWithBadge.tsx @@ -0,0 +1,37 @@ +import * as React from 'react'; +import { styled } from '@mui/material/styles'; +import IconButton from '@mui/material/IconButton'; +import Badge, { badgeClasses } from '@mui/material/Badge'; +import Stack from '@mui/material/Stack'; +import SaveIcon from '@mui/icons-material/Save'; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCartOutlined'; + +const CartBadge = styled(Badge)` + .${badgeClasses.badge} { + top: -12px; + right: -6px; + } +`; + +export default function IconButtonWithBadge() { + const [loading, setLoading] = React.useState(false); + React.useEffect(() => { + const timeout = setTimeout(() => { + setLoading(false); + }, 2000); + return () => clearTimeout(timeout); + }); + return ( + + + + + + + setLoading(true)}> + + + + + ); +} diff --git a/docs/data/material/components/buttons/IconButtonWithBadge.tsx.preview b/docs/data/material/components/buttons/IconButtonWithBadge.tsx.preview new file mode 100644 index 00000000000000..cfe404e63cb83d --- /dev/null +++ b/docs/data/material/components/buttons/IconButtonWithBadge.tsx.preview @@ -0,0 +1,9 @@ + + + + + + setLoading(true)}> + + + \ No newline at end of file diff --git a/docs/data/material/components/buttons/LoadingButtons.js b/docs/data/material/components/buttons/LoadingButtons.js index f2d71b178ab98d..09d568b124c92d 100644 --- a/docs/data/material/components/buttons/LoadingButtons.js +++ b/docs/data/material/components/buttons/LoadingButtons.js @@ -1,25 +1,45 @@ import * as React from 'react'; -import LoadingButton from '@mui/lab/LoadingButton'; +import Button from '@mui/material/Button'; import SaveIcon from '@mui/icons-material/Save'; import Stack from '@mui/material/Stack'; export default function LoadingButtons() { return ( - - - Submit - - - Fetch data - - + + + + + + + ); } diff --git a/docs/data/material/components/buttons/LoadingButtons.tsx b/docs/data/material/components/buttons/LoadingButtons.tsx index f2d71b178ab98d..09d568b124c92d 100644 --- a/docs/data/material/components/buttons/LoadingButtons.tsx +++ b/docs/data/material/components/buttons/LoadingButtons.tsx @@ -1,25 +1,45 @@ import * as React from 'react'; -import LoadingButton from '@mui/lab/LoadingButton'; +import Button from '@mui/material/Button'; import SaveIcon from '@mui/icons-material/Save'; import Stack from '@mui/material/Stack'; export default function LoadingButtons() { return ( - - - Submit - - - Fetch data - - + + + + + + + ); } diff --git a/docs/data/material/components/buttons/LoadingButtons.tsx.preview b/docs/data/material/components/buttons/LoadingButtons.tsx.preview deleted file mode 100644 index 9578d91a245686..00000000000000 --- a/docs/data/material/components/buttons/LoadingButtons.tsx.preview +++ /dev/null @@ -1,14 +0,0 @@ - - Submit - - - Fetch data - -} - variant="outlined" -> - Save - \ No newline at end of file diff --git a/docs/data/material/components/buttons/LoadingButtonsTransition.js b/docs/data/material/components/buttons/LoadingButtonsTransition.js index 21b0f2bd331d26..2278b2684fe7b5 100644 --- a/docs/data/material/components/buttons/LoadingButtonsTransition.js +++ b/docs/data/material/components/buttons/LoadingButtonsTransition.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import LoadingButton from '@mui/lab/LoadingButton'; +import Button from '@mui/material/Button'; import Box from '@mui/material/Box'; import FormControlLabel from '@mui/material/FormControlLabel'; import Switch from '@mui/material/Switch'; @@ -27,7 +27,7 @@ export default function LoadingButtonsTransition() { label="Loading" /> button': { m: 1 } }}> - Disabled - - + button': { m: 1 } }}> - + ); diff --git a/docs/data/material/components/buttons/LoadingButtonsTransition.tsx b/docs/data/material/components/buttons/LoadingButtonsTransition.tsx index 21b0f2bd331d26..2278b2684fe7b5 100644 --- a/docs/data/material/components/buttons/LoadingButtonsTransition.tsx +++ b/docs/data/material/components/buttons/LoadingButtonsTransition.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import LoadingButton from '@mui/lab/LoadingButton'; +import Button from '@mui/material/Button'; import Box from '@mui/material/Box'; import FormControlLabel from '@mui/material/FormControlLabel'; import Switch from '@mui/material/Switch'; @@ -27,7 +27,7 @@ export default function LoadingButtonsTransition() { label="Loading" /> button': { m: 1 } }}> - Disabled - - + button': { m: 1 } }}> - + ); diff --git a/docs/data/material/components/buttons/LoadingIconButton.js b/docs/data/material/components/buttons/LoadingIconButton.js new file mode 100644 index 00000000000000..6778d7281d47d7 --- /dev/null +++ b/docs/data/material/components/buttons/LoadingIconButton.js @@ -0,0 +1,21 @@ +import * as React from 'react'; +import Tooltip from '@mui/material/Tooltip'; +import IconButton from '@mui/material/IconButton'; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; + +export default function LoadingIconButton() { + const [loading, setLoading] = React.useState(false); + React.useEffect(() => { + const timeout = setTimeout(() => { + setLoading(false); + }, 2000); + return () => clearTimeout(timeout); + }); + return ( + + setLoading(true)} loading={loading}> + + + + ); +} diff --git a/docs/data/material/components/buttons/LoadingIconButton.tsx b/docs/data/material/components/buttons/LoadingIconButton.tsx new file mode 100644 index 00000000000000..6778d7281d47d7 --- /dev/null +++ b/docs/data/material/components/buttons/LoadingIconButton.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import Tooltip from '@mui/material/Tooltip'; +import IconButton from '@mui/material/IconButton'; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; + +export default function LoadingIconButton() { + const [loading, setLoading] = React.useState(false); + React.useEffect(() => { + const timeout = setTimeout(() => { + setLoading(false); + }, 2000); + return () => clearTimeout(timeout); + }); + return ( + + setLoading(true)} loading={loading}> + + + + ); +} diff --git a/docs/data/material/components/buttons/LoadingIconButton.tsx.preview b/docs/data/material/components/buttons/LoadingIconButton.tsx.preview new file mode 100644 index 00000000000000..9c9a8b0cbf868a --- /dev/null +++ b/docs/data/material/components/buttons/LoadingIconButton.tsx.preview @@ -0,0 +1,5 @@ + + setLoading(true)} loading={loading}> + + + \ No newline at end of file diff --git a/docs/data/material/components/buttons/buttons.md b/docs/data/material/components/buttons/buttons.md index 4da25aa7e55f5f..b2f86853e8fd08 100644 --- a/docs/data/material/components/buttons/buttons.md +++ b/docs/data/material/components/buttons/buttons.md @@ -1,7 +1,7 @@ --- productId: material-ui title: React Button component -components: Button, IconButton, ButtonBase, LoadingButton +components: Button, IconButton, ButtonBase materialDesign: https://m2.material.io/components/buttons githubLabel: 'component: button' waiAria: https://www.w3.org/WAI/ARIA/apg/patterns/button/ @@ -113,12 +113,34 @@ Use `color` prop to apply theme color palette to component. {{"demo": "IconButtonColors.js"}} +### Loading + +Use `loading` prop to set icon buttons in a loading state and disable interactions. + +{{"demo": "LoadingIconButton.js"}} + +### Badge + +You can use the [`Badge`](/material-ui/react-badge/) component to add a badge to an `IconButton`. + +{{"demo": "IconButtonWithBadge.js"}} + ## File upload To create a file upload button, turn the button into a label using `component="label"` and then create a visually-hidden input with type `file`. {{"demo": "InputFileUpload.js"}} +## Loading + +Use the `loading` prop to set buttons in a loading state and disable interactions. + +{{"demo": "LoadingButtons.js"}} + +Toggle the loading switch to see the transition between the different states. + +{{"demo": "LoadingButtonsTransition.js"}} + ## Customization Here are some examples of customizing the component. @@ -174,15 +196,3 @@ However: ``` This has the advantage of supporting any element, for instance, a link `` element. - -## Experimental APIs - -### Loading button - -[`@mui/lab`](/material-ui/about-the-lab/) offers loading buttons that can show loading state and disable interactions. - -{{"demo": "LoadingButtons.js"}} - -Toggle the loading switch to see the transition between the different states. - -{{"demo": "LoadingButtonsTransition.js"}} diff --git a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.js b/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.js index c51820532be8de..45c5878821cf2a 100644 --- a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.js +++ b/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.js @@ -2,7 +2,6 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { DialogsProvider, useDialogs } from '@toolpad/core/useDialogs'; import Button from '@mui/material/Button'; -import LoadingButton from '@mui/lab/LoadingButton'; import Dialog from '@mui/material/Dialog'; import Alert from '@mui/material/Alert'; import DialogTitle from '@mui/material/DialogTitle'; @@ -99,13 +98,9 @@ function DemoContent() { return (
- +
); diff --git a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx b/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx index 1fd85d043d9c2f..1d6aa7dacc434f 100644 --- a/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx +++ b/docs/data/material/components/dialogs/ToolpadDialogsNoSnap.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { DialogsProvider, useDialogs, DialogProps } from '@toolpad/core/useDialogs'; import Button from '@mui/material/Button'; -import LoadingButton from '@mui/lab/LoadingButton'; import Dialog from '@mui/material/Dialog'; import Alert from '@mui/material/Alert'; import DialogTitle from '@mui/material/DialogTitle'; @@ -80,13 +79,9 @@ function DemoContent() { return (
- +
); diff --git a/docs/data/material/migration/upgrade-to-v6/upgrade-to-v6.md b/docs/data/material/migration/upgrade-to-v6/upgrade-to-v6.md index 00559f268f5d28..c4fcc9af9dd1e4 100644 --- a/docs/data/material/migration/upgrade-to-v6/upgrade-to-v6.md +++ b/docs/data/material/migration/upgrade-to-v6/upgrade-to-v6.md @@ -356,9 +356,21 @@ As the `ListItem` no longer supports these props, the class names related to the +listItemButtonClasses.selected ``` -### Loading Button +### Button with Loading State -In v6, the `children` prop passed to the Loading Button component is now wrapped in a `` tag to avoid [issues](https://github.com/mui/material-ui/issues/27853) when using tools to translate websites. +As of `@mui/material` **v6.2.0**, the `LoadingButton` from Lab has been removed. Loading functionality is now part of the standard `Button` component. Update your import as follows: + +```diff +-import { LoadingButton } from '@mui/lab'; ++import { Button } from '@mui/material'; +``` + +```diff +-import LoadingButton from '@mui/lab/LoadingButton'; ++import Button from '@mui/material/Button'; +``` + +For more details, see the [Loading section](/material-ui/react-button/#loading-2) in the [Material UI `Button` documentation](/material-ui/react-button/). ### Typography diff --git a/docs/data/material/pagesApi.js b/docs/data/material/pagesApi.js index 2c6f1e2aca5155..7c0e8e172b7b08 100644 --- a/docs/data/material/pagesApi.js +++ b/docs/data/material/pagesApi.js @@ -70,7 +70,6 @@ module.exports = [ { pathname: '/material-ui/api/list-item-secondary-action' }, { pathname: '/material-ui/api/list-item-text' }, { pathname: '/material-ui/api/list-subheader' }, - { pathname: '/material-ui/api/loading-button' }, { pathname: '/material-ui/api/masonry' }, { pathname: '/material-ui/api/menu' }, { pathname: '/material-ui/api/menu-item' }, diff --git a/docs/pages/blog/2020-q2-update.md b/docs/pages/blog/2020-q2-update.md index 6d34a639194694..29f38b8eee2ea2 100644 --- a/docs/pages/blog/2020-q2-update.md +++ b/docs/pages/blog/2020-q2-update.md @@ -27,7 +27,7 @@ Here are the most significant improvements since March 2020: Adobe XD and Framer support are also up for consideration if they attract a significant audience, but not until we've polished the Sketch and Figma assets. -- 🔄 `LoadingButton` – [a new component in the lab](https://mui.com/material-ui/react-button/#loading-button). This work is influenced by the [concurrent UI patterns](https://17.reactjs.org/docs/concurrent-mode-patterns.html) presented by the React team. +- 🔄 `LoadingButton` – [a new component in the lab](https://v5.mui.com/material-ui/react-button/#loading-button). This work is influenced by the [concurrent UI patterns](https://17.reactjs.org/docs/concurrent-mode-patterns.html) presented by the React team. loading diff --git a/docs/pages/blog/mui-core-v5.md b/docs/pages/blog/mui-core-v5.md index 08bca2d4844f2a..4a2e55c467a95c 100644 --- a/docs/pages/blog/mui-core-v5.md +++ b/docs/pages/blog/mui-core-v5.md @@ -602,7 +602,7 @@ Having a separate lab package allows us to release breaking changes when necessa The following components are now available in the lab: -- [LoadingButton](/material-ui/react-button/#loading-button). It does what you would expect. It renders the `Button` with a configurable loading/pending state. +- [LoadingButton](https://v5.mui.com/material-ui/react-button/#loading-button). It does what you would expect. It renders the `Button` with a configurable loading/pending state. - [FocusTrap](/base-ui/react-focus-trap/). This component traps the keyboard focus within a DOM node. For example, it's used by the Modal to prevent tabbing out of the component for accessibility reasons. - [Masonry](/material-ui/react-masonry/). One great use case for this component is when using the `Grid` component leads to wasted space. It's frequently used in dashboards. diff --git a/docs/pages/material-ui/api/button.json b/docs/pages/material-ui/api/button.json index 04a03e76d983d5..996ab60f6e6a63 100644 --- a/docs/pages/material-ui/api/button.json +++ b/docs/pages/material-ui/api/button.json @@ -17,6 +17,18 @@ "endIcon": { "type": { "name": "node" } }, "fullWidth": { "type": { "name": "bool" }, "default": "false" }, "href": { "type": { "name": "string" } }, + "loading": { "type": { "name": "bool" }, "default": "false" }, + "loadingIndicator": { + "type": { "name": "node" }, + "default": "" + }, + "loadingPosition": { + "type": { + "name": "enum", + "description": "'center'
| 'end'
| 'start'" + }, + "default": "'center'" + }, "size": { "type": { "name": "union", @@ -182,6 +194,12 @@ "description": "Styles applied to the endIcon element if supplied.", "isGlobal": false }, + { + "key": "endIconLoadingEnd", + "className": "MuiButton-endIconLoadingEnd", + "description": "Styles applied to the endIcon element if `loading={true}` and `loadingPosition=\"end\"`.", + "isGlobal": false + }, { "key": "focusVisible", "className": "Mui-focusVisible", @@ -221,6 +239,36 @@ "isGlobal": false, "isDeprecated": true }, + { + "key": "loading", + "className": "MuiButton-loading", + "description": "Styles applied to the root element if `loading={true}`.", + "isGlobal": false + }, + { + "key": "loadingIndicator", + "className": "MuiButton-loadingIndicator", + "description": "Styles applied to the loadingIndicator element.", + "isGlobal": false + }, + { + "key": "loadingIndicatorCenter", + "className": "MuiButton-loadingIndicatorCenter", + "description": "Styles applied to the loadingIndicator element if `loadingPosition=\"center\"`.", + "isGlobal": false + }, + { + "key": "loadingIndicatorEnd", + "className": "MuiButton-loadingIndicatorEnd", + "description": "Styles applied to the loadingIndicator element if `loadingPosition=\"end\"`.", + "isGlobal": false + }, + { + "key": "loadingIndicatorStart", + "className": "MuiButton-loadingIndicatorStart", + "description": "Styles applied to the loadingIndicator element if `loadingPosition=\"start\"`.", + "isGlobal": false + }, { "key": "outlined", "className": "MuiButton-outlined", @@ -327,6 +375,12 @@ "description": "Styles applied to the startIcon element if supplied.", "isGlobal": false }, + { + "key": "startIconLoadingStart", + "className": "MuiButton-startIconLoadingStart", + "description": "Styles applied to the startIcon element if `loading={true}` and `loadingPosition=\"start\"`.", + "isGlobal": false + }, { "key": "text", "className": "MuiButton-text", diff --git a/docs/pages/material-ui/api/icon-button.json b/docs/pages/material-ui/api/icon-button.json index 752030e32dcce9..09cb6b9e7dc49e 100644 --- a/docs/pages/material-ui/api/icon-button.json +++ b/docs/pages/material-ui/api/icon-button.json @@ -19,6 +19,11 @@ }, "default": "false" }, + "loading": { "type": { "name": "bool" }, "default": "false" }, + "loadingIndicator": { + "type": { "name": "node" }, + "default": "" + }, "size": { "type": { "name": "union", @@ -100,6 +105,18 @@ "description": "Styles applied to the root element if `edge=\"start\"`.", "isGlobal": false }, + { + "key": "loading", + "className": "MuiIconButton-loading", + "description": "Styles applied to the root element if `loading={true}`.", + "isGlobal": false + }, + { + "key": "loadingIndicator", + "className": "MuiIconButton-loadingIndicator", + "description": "Styles applied to the loadingIndicator element.", + "isGlobal": false + }, { "key": "root", "className": "MuiIconButton-root", diff --git a/docs/pages/material-ui/api/loading-button.js b/docs/pages/material-ui/api/loading-button.js deleted file mode 100644 index cab581691ab572..00000000000000 --- a/docs/pages/material-ui/api/loading-button.js +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react'; -import ApiPage from 'docs/src/modules/components/ApiPage'; -import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; -import jsonPageContent from './loading-button.json'; - -export default function Page(props) { - const { descriptions, pageContent } = props; - return ; -} - -Page.getInitialProps = () => { - const req = require.context( - 'docs/translations/api-docs/loading-button', - false, - /\.\/loading-button.*.json$/, - ); - const descriptions = mapApiPageTranslations(req); - - return { - descriptions, - pageContent: jsonPageContent, - }; -}; diff --git a/docs/pages/material-ui/api/loading-button.json b/docs/pages/material-ui/api/loading-button.json deleted file mode 100644 index 8155927a65f266..00000000000000 --- a/docs/pages/material-ui/api/loading-button.json +++ /dev/null @@ -1,453 +0,0 @@ -{ - "props": { - "children": { "type": { "name": "node" } }, - "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, - "disabled": { "type": { "name": "bool" }, "default": "false" }, - "loading": { "type": { "name": "bool" }, "default": "false" }, - "loadingIndicator": { - "type": { "name": "node" }, - "default": "" - }, - "loadingPosition": { - "type": { - "name": "custom", - "description": "'start'
| 'end'
| 'center'" - }, - "default": "'center'" - }, - "sx": { - "type": { - "name": "union", - "description": "Array<func
| object
| bool>
| func
| object" - }, - "additionalInfo": { "sx": true } - }, - "variant": { - "type": { - "name": "union", - "description": "'contained'
| 'outlined'
| 'text'
| string" - }, - "default": "'text'" - } - }, - "name": "LoadingButton", - "imports": [ - "import LoadingButton from '@mui/lab/LoadingButton';", - "import { LoadingButton } from '@mui/lab';" - ], - "classes": [ - { - "key": "colorError", - "className": "MuiLoadingButton-colorError", - "description": "Styles applied to the root element if `color=\"error\"`.", - "isGlobal": false - }, - { - "key": "colorInfo", - "className": "MuiLoadingButton-colorInfo", - "description": "Styles applied to the root element if `color=\"info\"`.", - "isGlobal": false - }, - { - "key": "colorInherit", - "className": "MuiLoadingButton-colorInherit", - "description": "Styles applied to the root element if `color=\"inherit\"`.", - "isGlobal": false - }, - { - "key": "colorPrimary", - "className": "MuiLoadingButton-colorPrimary", - "description": "Styles applied to the root element if `color=\"primary\"`.", - "isGlobal": false - }, - { - "key": "colorSecondary", - "className": "MuiLoadingButton-colorSecondary", - "description": "Styles applied to the root element if `color=\"secondary\"`.", - "isGlobal": false - }, - { - "key": "colorSuccess", - "className": "MuiLoadingButton-colorSuccess", - "description": "Styles applied to the root element if `color=\"success\"`.", - "isGlobal": false - }, - { - "key": "colorWarning", - "className": "MuiLoadingButton-colorWarning", - "description": "Styles applied to the root element if `color=\"warning\"`.", - "isGlobal": false - }, - { - "key": "contained", - "className": "MuiLoadingButton-contained", - "description": "Styles applied to the root element if `variant=\"contained\"`.", - "isGlobal": false - }, - { - "key": "containedError", - "className": "MuiLoadingButton-containedError", - "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"error\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedInfo", - "className": "MuiLoadingButton-containedInfo", - "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"info\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedInherit", - "className": "MuiLoadingButton-containedInherit", - "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"inherit\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedPrimary", - "className": "MuiLoadingButton-containedPrimary", - "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"primary\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedSecondary", - "className": "MuiLoadingButton-containedSecondary", - "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"secondary\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedSizeLarge", - "className": "MuiLoadingButton-containedSizeLarge", - "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"contained\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedSizeMedium", - "className": "MuiLoadingButton-containedSizeMedium", - "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"contained\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedSizeSmall", - "className": "MuiLoadingButton-containedSizeSmall", - "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"contained\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedSuccess", - "className": "MuiLoadingButton-containedSuccess", - "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"success\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "containedWarning", - "className": "MuiLoadingButton-containedWarning", - "description": "Styles applied to the root element if `variant=\"contained\"` and `color=\"warning\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "disabled", - "className": "Mui-disabled", - "description": "State class applied to the root element if `disabled={true}`.", - "isGlobal": true - }, - { - "key": "disableElevation", - "className": "MuiLoadingButton-disableElevation", - "description": "Styles applied to the root element if `disableElevation={true}`.", - "isGlobal": false - }, - { - "key": "endIcon", - "className": "MuiLoadingButton-endIcon", - "description": "Styles applied to the endIcon element if supplied.", - "isGlobal": false - }, - { - "key": "endIconLoadingEnd", - "className": "MuiLoadingButton-endIconLoadingEnd", - "description": "Styles applied to the endIcon element if `loading={true}` and `loadingPosition=\"end\"`.", - "isGlobal": false - }, - { - "key": "focusVisible", - "className": "Mui-focusVisible", - "description": "State class applied to the ButtonBase root element if the button is keyboard focused.", - "isGlobal": true - }, - { - "key": "fullWidth", - "className": "MuiLoadingButton-fullWidth", - "description": "Styles applied to the root element if `fullWidth={true}`.", - "isGlobal": false - }, - { - "key": "icon", - "className": "MuiLoadingButton-icon", - "description": "Styles applied to the icon element if supplied", - "isGlobal": false - }, - { - "key": "iconSizeLarge", - "className": "MuiLoadingButton-iconSizeLarge", - "description": "Styles applied to the icon element if supplied and `size=\"large\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "iconSizeMedium", - "className": "MuiLoadingButton-iconSizeMedium", - "description": "Styles applied to the icon element if supplied and `size=\"medium\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "iconSizeSmall", - "className": "MuiLoadingButton-iconSizeSmall", - "description": "Styles applied to the icon element if supplied and `size=\"small\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "label", - "className": "MuiLoadingButton-label", - "description": "Styles applied to the span element that wraps the children.", - "isGlobal": false - }, - { - "key": "loading", - "className": "MuiLoadingButton-loading", - "description": "Styles applied to the root element if `loading={true}`.", - "isGlobal": false - }, - { - "key": "loadingIndicator", - "className": "MuiLoadingButton-loadingIndicator", - "description": "Styles applied to the loadingIndicator element.", - "isGlobal": false - }, - { - "key": "loadingIndicatorCenter", - "className": "MuiLoadingButton-loadingIndicatorCenter", - "description": "Styles applied to the loadingIndicator element if `loadingPosition=\"center\"`.", - "isGlobal": false - }, - { - "key": "loadingIndicatorEnd", - "className": "MuiLoadingButton-loadingIndicatorEnd", - "description": "Styles applied to the loadingIndicator element if `loadingPosition=\"end\"`.", - "isGlobal": false - }, - { - "key": "loadingIndicatorStart", - "className": "MuiLoadingButton-loadingIndicatorStart", - "description": "Styles applied to the loadingIndicator element if `loadingPosition=\"start\"`.", - "isGlobal": false - }, - { - "key": "outlined", - "className": "MuiLoadingButton-outlined", - "description": "Styles applied to the root element if `variant=\"outlined\"`.", - "isGlobal": false - }, - { - "key": "outlinedError", - "className": "MuiLoadingButton-outlinedError", - "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"error\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedInfo", - "className": "MuiLoadingButton-outlinedInfo", - "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"info\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedInherit", - "className": "MuiLoadingButton-outlinedInherit", - "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"inherit\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedPrimary", - "className": "MuiLoadingButton-outlinedPrimary", - "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"primary\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedSecondary", - "className": "MuiLoadingButton-outlinedSecondary", - "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"secondary\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedSizeLarge", - "className": "MuiLoadingButton-outlinedSizeLarge", - "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"outlined\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedSizeMedium", - "className": "MuiLoadingButton-outlinedSizeMedium", - "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"outlined\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedSizeSmall", - "className": "MuiLoadingButton-outlinedSizeSmall", - "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"outlined\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedSuccess", - "className": "MuiLoadingButton-outlinedSuccess", - "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"success\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "outlinedWarning", - "className": "MuiLoadingButton-outlinedWarning", - "description": "Styles applied to the root element if `variant=\"outlined\"` and `color=\"warning\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "root", - "className": "MuiLoadingButton-root", - "description": "Styles applied to the root element.", - "isGlobal": false - }, - { - "key": "sizeLarge", - "className": "MuiLoadingButton-sizeLarge", - "description": "Styles applied to the root element if `size=\"large\"`.", - "isGlobal": false - }, - { - "key": "sizeMedium", - "className": "MuiLoadingButton-sizeMedium", - "description": "Styles applied to the root element if `size=\"medium\"`.", - "isGlobal": false - }, - { - "key": "sizeSmall", - "className": "MuiLoadingButton-sizeSmall", - "description": "Styles applied to the root element if `size=\"small\"`.", - "isGlobal": false - }, - { - "key": "startIcon", - "className": "MuiLoadingButton-startIcon", - "description": "Styles applied to the startIcon element if supplied.", - "isGlobal": false - }, - { - "key": "startIconLoadingStart", - "className": "MuiLoadingButton-startIconLoadingStart", - "description": "Styles applied to the startIcon element if `loading={true}` and `loadingPosition=\"start\"`.", - "isGlobal": false - }, - { - "key": "text", - "className": "MuiLoadingButton-text", - "description": "Styles applied to the root element if `variant=\"text\"`.", - "isGlobal": false - }, - { - "key": "textError", - "className": "MuiLoadingButton-textError", - "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"error\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textInfo", - "className": "MuiLoadingButton-textInfo", - "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"info\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textInherit", - "className": "MuiLoadingButton-textInherit", - "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"inherit\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textPrimary", - "className": "MuiLoadingButton-textPrimary", - "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"primary\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textSecondary", - "className": "MuiLoadingButton-textSecondary", - "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"secondary\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textSizeLarge", - "className": "MuiLoadingButton-textSizeLarge", - "description": "Styles applied to the root element if `size=\"large\"` and `variant=\"text\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textSizeMedium", - "className": "MuiLoadingButton-textSizeMedium", - "description": "Styles applied to the root element if `size=\"medium\"` and `variant=\"text\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textSizeSmall", - "className": "MuiLoadingButton-textSizeSmall", - "description": "Styles applied to the root element if `size=\"small\"` and `variant=\"text\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textSuccess", - "className": "MuiLoadingButton-textSuccess", - "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"success\"`.", - "isGlobal": false, - "isDeprecated": true - }, - { - "key": "textWarning", - "className": "MuiLoadingButton-textWarning", - "description": "Styles applied to the root element if `variant=\"text\"` and `color=\"warning\"`.", - "isGlobal": false, - "isDeprecated": true - } - ], - "spread": true, - "themeDefaultProps": true, - "muiName": "MuiLoadingButton", - "forwardsRefTo": "HTMLButtonElement", - "filename": "/packages/mui-lab/src/LoadingButton/LoadingButton.js", - "inheritance": { "component": "Button", "pathname": "/material-ui/api/button/" }, - "demos": "
", - "cssComponent": false -} diff --git a/docs/src/pagesApi.js b/docs/src/pagesApi.js index c9829209aec475..8c040f448a4d23 100644 --- a/docs/src/pagesApi.js +++ b/docs/src/pagesApi.js @@ -67,7 +67,6 @@ module.exports = [ { pathname: '/api-docs/list-item-secondary-action' }, { pathname: '/api-docs/list-item-text' }, { pathname: '/api-docs/list-subheader' }, - { pathname: '/api-docs/loading-button' }, { pathname: '/api-docs/masonry' }, { pathname: '/api-docs/menu' }, { pathname: '/api-docs/menu-item' }, diff --git a/docs/translations/api-docs/button/button.json b/docs/translations/api-docs/button/button.json index 1e9426f65ac3de..dac8f6e775b631 100644 --- a/docs/translations/api-docs/button/button.json +++ b/docs/translations/api-docs/button/button.json @@ -24,6 +24,15 @@ "href": { "description": "The URL to link to when the button is clicked. If defined, an a element will be used as the root node." }, + "loading": { + "description": "If true, the loading indicator is shown and the button becomes disabled." + }, + "loadingIndicator": { + "description": "Element placed before the children if the button is in loading state. The node should contain an element with role="progressbar" with an accessible name. By default we render a CircularProgress that is labelled by the button itself." + }, + "loadingPosition": { + "description": "The loading indicator can be positioned on the start, end, or the center of the button." + }, "size": { "description": "The size of the component. small is equivalent to the dense button styling." }, @@ -149,6 +158,11 @@ "nodeName": "the endIcon element", "conditions": "supplied" }, + "endIconLoadingEnd": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the endIcon element", + "conditions": "loading={true} and loadingPosition=\"end\"" + }, "focusVisible": { "description": "State class applied to {{nodeName}} if {{conditions}}.", "nodeName": "the ButtonBase root element", @@ -178,6 +192,30 @@ "conditions": "supplied and size=\"small\"", "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeSmall classes instead. See Migrating from deprecated APIs for more details." }, + "loading": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "loading={true}" + }, + "loadingIndicator": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the loadingIndicator element" + }, + "loadingIndicatorCenter": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the loadingIndicator element", + "conditions": "loadingPosition=\"center\"" + }, + "loadingIndicatorEnd": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the loadingIndicator element", + "conditions": "loadingPosition=\"end\"" + }, + "loadingIndicatorStart": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the loadingIndicator element", + "conditions": "loadingPosition=\"start\"" + }, "outlined": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the root element", @@ -264,6 +302,11 @@ "nodeName": "the startIcon element", "conditions": "supplied" }, + "startIconLoadingStart": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the startIcon element", + "conditions": "loading={true} and loadingPosition=\"start\"" + }, "text": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", "nodeName": "the root element", diff --git a/docs/translations/api-docs/icon-button/icon-button.json b/docs/translations/api-docs/icon-button/icon-button.json index 76558bfba72680..03aeb7ec720d0c 100644 --- a/docs/translations/api-docs/icon-button/icon-button.json +++ b/docs/translations/api-docs/icon-button/icon-button.json @@ -16,6 +16,12 @@ "edge": { "description": "If given, uses a negative margin to counteract the padding on one side (this is often helpful for aligning the left or right side of the icon with content above or below, without ruining the border size and shape)." }, + "loading": { + "description": "If true, the loading indicator is shown and the button becomes disabled." + }, + "loadingIndicator": { + "description": "Element placed before the children if the button is in loading state. The node should contain an element with role="progressbar" with an accessible name. By default we render a CircularProgress that is labelled by the button itself." + }, "size": { "description": "The size of the component. small is equivalent to the dense button styling." }, @@ -74,6 +80,15 @@ "nodeName": "the root element", "conditions": "edge=\"start\"" }, + "loading": { + "description": "Styles applied to {{nodeName}} if {{conditions}}.", + "nodeName": "the root element", + "conditions": "loading={true}" + }, + "loadingIndicator": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the loadingIndicator element" + }, "root": { "description": "Styles applied to the root element." }, "sizeLarge": { "description": "Styles applied to {{nodeName}} if {{conditions}}.", diff --git a/docs/translations/api-docs/loading-button/loading-button.json b/docs/translations/api-docs/loading-button/loading-button.json deleted file mode 100644 index 9babb1623d14c9..00000000000000 --- a/docs/translations/api-docs/loading-button/loading-button.json +++ /dev/null @@ -1,356 +0,0 @@ -{ - "componentDescription": "", - "propDescriptions": { - "children": { "description": "The content of the component." }, - "classes": { "description": "Override or extend the styles applied to the component." }, - "disabled": { "description": "If true, the component is disabled." }, - "loading": { - "description": "If true, the loading indicator is shown and the button becomes disabled." - }, - "loadingIndicator": { - "description": "Element placed before the children if the button is in loading state. The node should contain an element with role="progressbar" with an accessible name. By default we render a CircularProgress that is labelled by the button itself." - }, - "loadingPosition": { - "description": "The loading indicator can be positioned on the start, end, or the center of the button." - }, - "sx": { - "description": "The system prop that allows defining system overrides as well as additional CSS styles." - }, - "variant": { "description": "The variant to use." } - }, - "classDescriptions": { - "colorError": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "color=\"error\"" - }, - "colorInfo": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "color=\"info\"" - }, - "colorInherit": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "color=\"inherit\"" - }, - "colorPrimary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "color=\"primary\"" - }, - "colorSecondary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "color=\"secondary\"" - }, - "colorSuccess": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "color=\"success\"" - }, - "colorWarning": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "color=\"warning\"" - }, - "contained": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\"" - }, - "containedError": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\" and color=\"error\"", - "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." - }, - "containedInfo": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\" and color=\"info\"", - "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." - }, - "containedInherit": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\" and color=\"inherit\"", - "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." - }, - "containedPrimary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\" and color=\"primary\"", - "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." - }, - "containedSecondary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\" and color=\"secondary\"", - "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." - }, - "containedSizeLarge": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"large\" and variant=\"contained\"", - "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." - }, - "containedSizeMedium": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"medium\" and variant=\"contained\"", - "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." - }, - "containedSizeSmall": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"small\" and variant=\"contained\"", - "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-contained classes instead. See Migrating from deprecated APIs for more details." - }, - "containedSuccess": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\" and color=\"success\"", - "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." - }, - "containedWarning": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"contained\" and color=\"warning\"", - "deprecationInfo": "Combine the .MuiButton-contained and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." - }, - "disabled": { - "description": "State class applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "disabled={true}" - }, - "disableElevation": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "disableElevation={true}" - }, - "endIcon": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the endIcon element", - "conditions": "supplied" - }, - "endIconLoadingEnd": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the endIcon element", - "conditions": "loading={true} and loadingPosition=\"end\"" - }, - "focusVisible": { - "description": "State class applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the ButtonBase root element", - "conditions": "the button is keyboard focused" - }, - "fullWidth": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "fullWidth={true}" - }, - "icon": { "description": "Styles applied to the icon element if supplied" }, - "iconSizeLarge": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the icon element", - "conditions": "supplied and size=\"large\"", - "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeLarge classes instead. See Migrating from deprecated APIs for more details." - }, - "iconSizeMedium": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the icon element", - "conditions": "supplied and size=\"medium\"", - "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeMedium classes instead. See Migrating from deprecated APIs for more details." - }, - "iconSizeSmall": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the icon element", - "conditions": "supplied and size=\"small\"", - "deprecationInfo": "Combine the .MuiButton-icon and .MuiButtonSizeSmall classes instead. See Migrating from deprecated APIs for more details." - }, - "label": { - "description": "Styles applied to {{nodeName}}.", - "nodeName": "the span element that wraps the children" - }, - "loading": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "loading={true}" - }, - "loadingIndicator": { - "description": "Styles applied to {{nodeName}}.", - "nodeName": "the loadingIndicator element" - }, - "loadingIndicatorCenter": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the loadingIndicator element", - "conditions": "loadingPosition=\"center\"" - }, - "loadingIndicatorEnd": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the loadingIndicator element", - "conditions": "loadingPosition=\"end\"" - }, - "loadingIndicatorStart": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the loadingIndicator element", - "conditions": "loadingPosition=\"start\"" - }, - "outlined": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\"" - }, - "outlinedError": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\" and color=\"error\"", - "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedInfo": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\" and color=\"info\"", - "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedInherit": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\" and color=\"inherit\"", - "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedPrimary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\" and color=\"primary\"", - "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedSecondary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\" and color=\"secondary\"", - "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedSizeLarge": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"large\" and variant=\"outlined\"", - "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedSizeMedium": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"medium\" and variant=\"outlined\"", - "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedSizeSmall": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"small\" and variant=\"outlined\"", - "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-outlined classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedSuccess": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\" and color=\"success\"", - "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." - }, - "outlinedWarning": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"outlined\" and color=\"warning\"", - "deprecationInfo": "Combine the .MuiButton-outlined and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." - }, - "root": { "description": "Styles applied to the root element." }, - "sizeLarge": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"large\"" - }, - "sizeMedium": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"medium\"" - }, - "sizeSmall": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"small\"" - }, - "startIcon": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the startIcon element", - "conditions": "supplied" - }, - "startIconLoadingStart": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the startIcon element", - "conditions": "loading={true} and loadingPosition=\"start\"" - }, - "text": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\"" - }, - "textError": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\" and color=\"error\"", - "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorError classes instead. See Migrating from deprecated APIs for more details." - }, - "textInfo": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\" and color=\"info\"", - "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorInfo classes instead. See Migrating from deprecated APIs for more details." - }, - "textInherit": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\" and color=\"inherit\"", - "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorInherit classes instead. See Migrating from deprecated APIs for more details." - }, - "textPrimary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\" and color=\"primary\"", - "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorPrimary classes instead. See Migrating from deprecated APIs for more details." - }, - "textSecondary": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\" and color=\"secondary\"", - "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorSecondary classes instead. See Migrating from deprecated APIs for more details." - }, - "textSizeLarge": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"large\" and variant=\"text\"", - "deprecationInfo": "Combine the .MuiButton-sizeLarge and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." - }, - "textSizeMedium": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"medium\" and variant=\"text\"", - "deprecationInfo": "Combine the .MuiButton-sizeMedium and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." - }, - "textSizeSmall": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "size=\"small\" and variant=\"text\"", - "deprecationInfo": "Combine the .MuiButton-sizeSmall and .MuiButton-text classes instead. See Migrating from deprecated APIs for more details." - }, - "textSuccess": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\" and color=\"success\"", - "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorSuccess classes instead. See Migrating from deprecated APIs for more details." - }, - "textWarning": { - "description": "Styles applied to {{nodeName}} if {{conditions}}.", - "nodeName": "the root element", - "conditions": "variant=\"text\" and color=\"warning\"", - "deprecationInfo": "Combine the .MuiButton-text and .MuiButton-colorWarning classes instead. See Migrating from deprecated APIs for more details." - } - } -} diff --git a/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts b/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts index 193b192ddf029d..da2a708e023be3 100644 --- a/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts +++ b/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts @@ -1,80 +1,2 @@ -import { ExtendButton, ExtendButtonTypeMap, ButtonClasses } from '@mui/material/Button'; -import { OverrideProps } from '@mui/material/OverridableComponent'; -import { Theme } from '@mui/material/styles'; -import { SxProps } from '@mui/system'; - -export interface LoadingButtonOwnProps { - /** - * Override or extend the styles applied to the component. - */ - classes?: Partial & { - /** Styles applied to the root element. */ - root?: string; - /** Styles applied to the span element that wraps the children. */ - label?: string; - /** Styles applied to the root element if `loading={true}`. */ - loading?: string; - /** Styles applied to the loadingIndicator element. */ - loadingIndicator?: string; - /** Styles applied to the loadingIndicator element if `loadingPosition="center"`. */ - loadingIndicatorCenter?: string; - /** Styles applied to the loadingIndicator element if `loadingPosition="start"`. */ - loadingIndicatorStart?: string; - /** Styles applied to the loadingIndicator element if `loadingPosition="end"`. */ - loadingIndicatorEnd?: string; - /** Styles applied to the endIcon element if `loading={true}` and `loadingPosition="end"`. */ - endIconLoadingEnd?: string; - /** Styles applied to the startIcon element if `loading={true}` and `loadingPosition="start"`. */ - startIconLoadingStart?: string; - }; - /** - * If `true`, the loading indicator is shown and the button becomes disabled. - * @default false - */ - loading?: boolean; - /** - * Element placed before the children if the button is in loading state. - * The node should contain an element with `role="progressbar"` with an accessible name. - * By default we render a `CircularProgress` that is labelled by the button itself. - * @default - */ - loadingIndicator?: React.ReactNode; - /** - * The loading indicator can be positioned on the start, end, or the center of the button. - * @default 'center' - */ - loadingPosition?: 'start' | 'end' | 'center'; - /** - * The system prop that allows defining system overrides as well as additional CSS styles. - */ - sx?: SxProps; -} - -export type LoadingButtonTypeMap< - AdditionalProps = {}, - RootComponent extends React.ElementType = 'button', -> = ExtendButtonTypeMap<{ - props: AdditionalProps & LoadingButtonOwnProps; - defaultComponent: RootComponent; -}>; - -/** - * - * Demos: - * - * - [Button Group](https://mui.com/material-ui/react-button-group/) - * - [Button](https://mui.com/material-ui/react-button/) - * - * API: - * - * - [LoadingButton API](https://mui.com/material-ui/api/loading-button/) - * - inherits [Button API](https://mui.com/material-ui/api/button/) - */ -declare const LoadingButton: ExtendButton; - -export type LoadingButtonProps< - RootComponent extends React.ElementType = LoadingButtonTypeMap['defaultComponent'], - AdditionalProps = {}, -> = OverrideProps, RootComponent>; - -export default LoadingButton; +export { default } from '@mui/material/Button'; +export * from '@mui/material/Button'; diff --git a/packages/mui-lab/src/LoadingButton/LoadingButton.js b/packages/mui-lab/src/LoadingButton/LoadingButton.js index 12f0997a888d09..8c4529a715bf4b 100644 --- a/packages/mui-lab/src/LoadingButton/LoadingButton.js +++ b/packages/mui-lab/src/LoadingButton/LoadingButton.js @@ -1,350 +1,29 @@ 'use client'; import * as React from 'react'; -import PropTypes from 'prop-types'; -import { chainPropTypes } from '@mui/utils'; -import { - capitalize, - unstable_useId as useId, - unstable_memoTheme as memoTheme, -} from '@mui/material/utils'; -import { unstable_composeClasses as composeClasses } from '@mui/base'; -import { useDefaultProps } from '@mui/material/DefaultPropsProvider'; import Button from '@mui/material/Button'; -import { ButtonGroupContext } from '@mui/material/ButtonGroup'; -import CircularProgress from '@mui/material/CircularProgress'; -import resolveProps from '@mui/utils/resolveProps'; -import { styled } from '../zero-styled'; -import loadingButtonClasses, { getLoadingButtonUtilityClass } from './loadingButtonClasses'; -const useUtilityClasses = (ownerState) => { - const { loading, loadingPosition, classes } = ownerState; - - const slots = { - root: ['root', loading && 'loading'], - label: ['label'], - startIcon: [loading && `startIconLoading${capitalize(loadingPosition)}`], - endIcon: [loading && `endIconLoading${capitalize(loadingPosition)}`], - loadingIndicator: [ - 'loadingIndicator', - loading && `loadingIndicator${capitalize(loadingPosition)}`, - ], - }; - - const composedClasses = composeClasses(slots, getLoadingButtonUtilityClass, classes); - - return { - ...classes, // forward the outlined, color, etc. classes to Button - ...composedClasses, - }; +let warnedOnce = false; + +const warn = () => { + if (!warnedOnce) { + console.warn( + [ + 'MUI: The LoadingButton component functionality is now part of the Button component from Material UI.', + '', + "You should use `import { Button } from '@mui/material'`", + "or `import Button from '@mui/material/Button'`", + ].join('\n'), + ); + + warnedOnce = true; + } }; -// TODO use `import rootShouldForwardProp from '../styles/rootShouldForwardProp';` once move to core -const rootShouldForwardProp = (prop) => - prop !== 'ownerState' && prop !== 'theme' && prop !== 'sx' && prop !== 'as' && prop !== 'classes'; -const LoadingButtonRoot = styled(Button, { - shouldForwardProp: (prop) => rootShouldForwardProp(prop) || prop === 'classes', - name: 'MuiLoadingButton', - slot: 'Root', - overridesResolver: (props, styles) => { - return [ - styles.root, - styles.startIconLoadingStart && { - [`& .${loadingButtonClasses.startIconLoadingStart}`]: styles.startIconLoadingStart, - }, - styles.endIconLoadingEnd && { - [`& .${loadingButtonClasses.endIconLoadingEnd}`]: styles.endIconLoadingEnd, - }, - ]; - }, -})( - memoTheme(({ theme }) => ({ - display: 'inline-flex', - [`& .${loadingButtonClasses.startIconLoadingStart}, & .${loadingButtonClasses.endIconLoadingEnd}`]: - { - transition: theme.transitions.create(['opacity'], { - duration: theme.transitions.duration.short, - }), - opacity: 0, - }, - variants: [ - { - props: { - loadingPosition: 'center', - }, - style: { - transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color'], { - duration: theme.transitions.duration.short, - }), - [`&.${loadingButtonClasses.loading}`]: { - color: 'transparent', - }, - }, - }, - { - props: ({ ownerState }) => ownerState.loadingPosition === 'start' && ownerState.fullWidth, - style: { - [`& .${loadingButtonClasses.startIconLoadingStart}, & .${loadingButtonClasses.endIconLoadingEnd}`]: - { - transition: theme.transitions.create(['opacity'], { - duration: theme.transitions.duration.short, - }), - opacity: 0, - marginRight: -8, - }, - }, - }, - { - props: ({ ownerState }) => ownerState.loadingPosition === 'end' && ownerState.fullWidth, - style: { - [`& .${loadingButtonClasses.startIconLoadingStart}, & .${loadingButtonClasses.endIconLoadingEnd}`]: - { - transition: theme.transitions.create(['opacity'], { - duration: theme.transitions.duration.short, - }), - opacity: 0, - marginLeft: -8, - }, - }, - }, - ], - })), -); - -const LoadingButtonLoadingIndicator = styled('span', { - name: 'MuiLoadingButton', - slot: 'LoadingIndicator', - overridesResolver: (props, styles) => { - const { ownerState } = props; - return [ - styles.loadingIndicator, - styles[`loadingIndicator${capitalize(ownerState.loadingPosition)}`], - ]; - }, -})( - memoTheme(({ theme }) => ({ - position: 'absolute', - visibility: 'visible', - display: 'flex', - variants: [ - { - props: { - loadingPosition: 'start', - size: 'small', - }, - style: { - left: 10, - }, - }, - { - props: ({ loadingPosition, ownerState }) => - loadingPosition === 'start' && ownerState.size !== 'small', - style: { - left: 14, - }, - }, - { - props: { - variant: 'text', - loadingPosition: 'start', - }, - style: { - left: 6, - }, - }, - { - props: { - loadingPosition: 'center', - }, - style: { - left: '50%', - transform: 'translate(-50%)', - color: (theme.vars || theme).palette.action.disabled, - }, - }, - { - props: { - loadingPosition: 'end', - size: 'small', - }, - style: { - right: 10, - }, - }, - { - props: ({ loadingPosition, ownerState }) => - loadingPosition === 'end' && ownerState.size !== 'small', - style: { - right: 14, - }, - }, - { - props: { - variant: 'text', - loadingPosition: 'end', - }, - style: { - right: 6, - }, - }, - { - props: ({ ownerState }) => ownerState.loadingPosition === 'start' && ownerState.fullWidth, - style: { - position: 'relative', - left: -10, - }, - }, - { - props: ({ ownerState }) => ownerState.loadingPosition === 'end' && ownerState.fullWidth, - style: { - position: 'relative', - right: -10, - }, - }, - ], - })), -); +/** + * @ignore - do not document. + */ +export default React.forwardRef(function DeprecatedLoadingButton(props, ref) { + warn(); -const LoadingButtonLabel = styled('span', { - name: 'MuiLoadingButton', - slot: 'Label', - overridesResolver: (props, styles) => { - return [styles.label]; - }, -})({ - display: 'inherit', - alignItems: 'inherit', - justifyContent: 'inherit', + return ); }; + +function ClassesTest() { + return ( + + ); +} diff --git a/packages/mui-material/src/Button/Button.test.js b/packages/mui-material/src/Button/Button.test.js index 5d57fa23d002a0..7d3c1033a2f376 100644 --- a/packages/mui-material/src/Button/Button.test.js +++ b/packages/mui-material/src/Button/Button.test.js @@ -1,6 +1,6 @@ import * as React from 'react'; import { expect } from 'chai'; -import { createRenderer, screen, simulateKeyboardDevice } from '@mui/internal-test-utils'; +import { createRenderer, screen, simulateKeyboardDevice, within } from '@mui/internal-test-utils'; import { ClassNames } from '@emotion/react'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import Button, { buttonClasses as classes } from '@mui/material/Button'; @@ -753,4 +753,46 @@ describe('); + + const button = screen.getByRole('button'); + const progressbar = within(button).getByRole('progressbar'); + expect(progressbar).toHaveAccessibleName('Submit'); + }); + }); + + describe('prop: loadingIndicator', () => { + it('is not rendered by default', () => { + render(); + + expect(screen.getByRole('button')).to.have.text('Test'); + }); + + it('is rendered before the children when `loading`', () => { + render( + , + ); + + expect(screen.getByRole('button')).to.have.text('loading…Test'); + }); + }); }); diff --git a/packages/mui-material/src/Button/buttonClasses.ts b/packages/mui-material/src/Button/buttonClasses.ts index e6abe7643e4736..3dd6b4ea750fb1 100644 --- a/packages/mui-material/src/Button/buttonClasses.ts +++ b/packages/mui-material/src/Button/buttonClasses.ts @@ -176,6 +176,20 @@ export interface ButtonClasses { colorInfo: string; /** Styles applied to the root element if `color="warning"`. */ colorWarning: string; + /** Styles applied to the root element if `loading={true}`. */ + loading: string; + /** Styles applied to the loadingIndicator element. */ + loadingIndicator: string; + /** Styles applied to the loadingIndicator element if `loadingPosition="center"`. */ + loadingIndicatorCenter: string; + /** Styles applied to the loadingIndicator element if `loadingPosition="start"`. */ + loadingIndicatorStart: string; + /** Styles applied to the loadingIndicator element if `loadingPosition="end"`. */ + loadingIndicatorEnd: string; + /** Styles applied to the endIcon element if `loading={true}` and `loadingPosition="end"`. */ + endIconLoadingEnd: string; + /** Styles applied to the startIcon element if `loading={true}` and `loadingPosition="start"`. */ + startIconLoadingStart: string; } export type ButtonClassKey = keyof ButtonClasses; @@ -239,6 +253,13 @@ const buttonClasses: ButtonClasses = generateUtilityClasses('MuiButton', [ 'iconSizeSmall', 'iconSizeMedium', 'iconSizeLarge', + 'loading', + 'loadingIndicator', + 'loadingIndicatorCenter', + 'loadingIndicatorStart', + 'loadingIndicatorEnd', + 'endIconLoadingEnd', + 'startIconLoadingStart', ]); export default buttonClasses; diff --git a/packages/mui-material/src/IconButton/IconButton.d.ts b/packages/mui-material/src/IconButton/IconButton.d.ts index 108d72d09ac0c3..8a0240b3706e5a 100644 --- a/packages/mui-material/src/IconButton/IconButton.d.ts +++ b/packages/mui-material/src/IconButton/IconButton.d.ts @@ -47,6 +47,18 @@ export interface IconButtonOwnProps { * @default false */ edge?: 'start' | 'end' | false; + /** + * If `true`, the loading indicator is shown and the button becomes disabled. + * @default false + */ + loading?: boolean; + /** + * Element placed before the children if the button is in loading state. + * The node should contain an element with `role="progressbar"` with an accessible name. + * By default we render a `CircularProgress` that is labelled by the button itself. + * @default + */ + loadingIndicator?: React.ReactNode; /** * The size of the component. * `small` is equivalent to the dense button styling. diff --git a/packages/mui-material/src/IconButton/IconButton.js b/packages/mui-material/src/IconButton/IconButton.js index 780a3ff72d3d19..9057a9c68daaf6 100644 --- a/packages/mui-material/src/IconButton/IconButton.js +++ b/packages/mui-material/src/IconButton/IconButton.js @@ -4,6 +4,8 @@ import PropTypes from 'prop-types'; import clsx from 'clsx'; import chainPropTypes from '@mui/utils/chainPropTypes'; import composeClasses from '@mui/utils/composeClasses'; +import { unstable_useId as useId } from '@mui/material/utils'; +import CircularProgress from '@mui/material/CircularProgress'; import { alpha } from '@mui/system/colorManipulator'; import { styled } from '../zero-styled'; import memoTheme from '../utils/memoTheme'; @@ -14,16 +16,18 @@ import capitalize from '../utils/capitalize'; import iconButtonClasses, { getIconButtonUtilityClass } from './iconButtonClasses'; const useUtilityClasses = (ownerState) => { - const { classes, disabled, color, edge, size } = ownerState; + const { classes, disabled, color, edge, size, loading } = ownerState; const slots = { root: [ 'root', + loading && 'loading', disabled && 'disabled', color !== 'default' && `color${capitalize(color)}`, edge && `edge${capitalize(edge)}`, `size${capitalize(size)}`, ], + loadingIndicator: ['loadingIndicator'], }; return composeClasses(slots, getIconButtonUtilityClass, classes); @@ -37,6 +41,7 @@ const IconButtonRoot = styled(ButtonBase, { return [ styles.root, + ownerState.loading && styles.loading, ownerState.color !== 'default' && styles[`color${capitalize(ownerState.color)}`], ownerState.edge && styles[`edge${capitalize(ownerState.edge)}`], styles[`size${capitalize(ownerState.size)}`], @@ -140,9 +145,27 @@ const IconButtonRoot = styled(ButtonBase, { backgroundColor: 'transparent', color: (theme.vars || theme).palette.action.disabled, }, + [`&.${iconButtonClasses.loading}`]: { + color: 'transparent', + }, })), ); +const IconButtonLoadingIndicator = styled('span', { + name: 'MuiIconButton', + slot: 'LoadingIndicator', + overridesResolver: (props, styles) => styles.loadingIndicator, +})(({ theme }) => ({ + display: 'none', + position: 'absolute', + visibility: 'visible', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + color: (theme.vars || theme).palette.action.disabled, + variants: [{ props: { loading: true }, style: { display: 'flex' } }], +})); + /** * Refer to the [Icons](/material-ui/icons/) section of the documentation * regarding the available icon options. @@ -157,15 +180,25 @@ const IconButton = React.forwardRef(function IconButton(inProps, ref) { disabled = false, disableFocusRipple = false, size = 'medium', + id: idProp, + loading = false, + loadingIndicator: loadingIndicatorProp, ...other } = props; + const id = useId(idProp); + const loadingIndicator = loadingIndicatorProp ?? ( + + ); + const ownerState = { ...props, edge, color, disabled, disableFocusRipple, + loading, + loadingIndicator, size, }; @@ -173,14 +206,18 @@ const IconButton = React.forwardRef(function IconButton(inProps, ref) { return ( + + {loading && loadingIndicator} + {children} ); @@ -264,6 +301,22 @@ IconButton.propTypes /* remove-proptypes */ = { * @default false */ edge: PropTypes.oneOf(['end', 'start', false]), + /** + * @ignore + */ + id: PropTypes.string, + /** + * If `true`, the loading indicator is shown and the button becomes disabled. + * @default false + */ + loading: PropTypes.bool, + /** + * Element placed before the children if the button is in loading state. + * The node should contain an element with `role="progressbar"` with an accessible name. + * By default we render a `CircularProgress` that is labelled by the button itself. + * @default + */ + loadingIndicator: PropTypes.node, /** * The size of the component. * `small` is equivalent to the dense button styling. diff --git a/packages/mui-material/src/IconButton/IconButton.test.js b/packages/mui-material/src/IconButton/IconButton.test.js index 827d2c91fb560d..e72515a6b0b309 100644 --- a/packages/mui-material/src/IconButton/IconButton.test.js +++ b/packages/mui-material/src/IconButton/IconButton.test.js @@ -1,7 +1,7 @@ import * as React from 'react'; import { expect } from 'chai'; import PropTypes from 'prop-types'; -import { createRenderer, reactMajor } from '@mui/internal-test-utils'; +import { createRenderer, reactMajor, screen, within } from '@mui/internal-test-utils'; import capitalize from '@mui/utils/capitalize'; import { ThemeProvider, createTheme } from '@mui/material/styles'; import IconButton, { iconButtonClasses as classes } from '@mui/material/IconButton'; @@ -161,4 +161,46 @@ describe('', () => { await ripple.startTouch(getByRole('button')); expect(container.querySelector('.touch-ripple')).to.equal(null); }); + + describe('prop: loading', () => { + it('disables the button', () => { + render(); + + const button = screen.getByRole('button'); + expect(button).to.have.property('tabIndex', -1); + expect(button).to.have.property('disabled', true); + }); + + it('cannot be enabled while `loading`', () => { + render(); + + expect(screen.getByRole('button')).to.have.property('disabled', true); + }); + + it('renders a progressbar that is labelled by the button', () => { + render(Submit); + + const button = screen.getByRole('button'); + const progressbar = within(button).getByRole('progressbar'); + expect(progressbar).toHaveAccessibleName('Submit'); + }); + }); + + describe('prop: loadingIndicator', () => { + it('is not rendered by default', () => { + render(Test); + + expect(screen.getByRole('button')).to.have.text('Test'); + }); + + it('is rendered before the children when `loading`', () => { + render( + + Test + , + ); + + expect(screen.getByRole('button')).to.have.text('loading…Test'); + }); + }); }); diff --git a/packages/mui-material/src/IconButton/iconButtonClasses.ts b/packages/mui-material/src/IconButton/iconButtonClasses.ts index 72eb0e109c497f..b65ac3b0d85264 100644 --- a/packages/mui-material/src/IconButton/iconButtonClasses.ts +++ b/packages/mui-material/src/IconButton/iconButtonClasses.ts @@ -30,6 +30,10 @@ export interface IconButtonClasses { sizeMedium: string; /** Styles applied to the root element if `size="large"`. */ sizeLarge: string; + /** Styles applied to the root element if `loading={true}`. */ + loading: string; + /** Styles applied to the loadingIndicator element. */ + loadingIndicator: string; } export type IconButtonClassKey = keyof IconButtonClasses; @@ -53,6 +57,8 @@ const iconButtonClasses: IconButtonClasses = generateUtilityClasses('MuiIconButt 'sizeSmall', 'sizeMedium', 'sizeLarge', + 'loading', + 'loadingIndicator', ]); export default iconButtonClasses; diff --git a/test/regressions/fixtures/Button/FullWidthLoadingButtons.js b/test/regressions/fixtures/Button/FullWidthLoadingButtons.js index e9f544630ef187..038f027e6b4b6a 100644 --- a/test/regressions/fixtures/Button/FullWidthLoadingButtons.js +++ b/test/regressions/fixtures/Button/FullWidthLoadingButtons.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import LoadingButton from '@mui/lab/LoadingButton'; +import Button from '@mui/material/Button'; import FormControlLabel from '@mui/material/FormControlLabel'; import Switch from '@mui/material/Switch'; import SaveIcon from '@mui/icons-material/Save'; @@ -27,10 +27,10 @@ export default function FullWidthLoadingButtonsTransition() { } label="Loading" /> - + ); } From fd97b178a64e987d480489161c3c196eb8c4751e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rodolfo=20Freitas?= Date: Thu, 14 Nov 2024 17:42:27 +0100 Subject: [PATCH 02/14] [blog] MUI X v8 alpha zero blog post (#44377) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Rodolfo Freitas Co-authored-by: Olivier Tassinari Co-authored-by: Ale <93217218+alelthomas@users.noreply.github.com> Co-authored-by: Sycamore <71297412+samuelsycamore@users.noreply.github.com> Co-authored-by: Nora <72460825+noraleonte@users.noreply.github.com> --- docs/pages/blog/mui-x-v8-alpha-zero.js | 7 ++ docs/pages/blog/mui-x-v8-alpha-zero.md | 99 ++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 docs/pages/blog/mui-x-v8-alpha-zero.js create mode 100644 docs/pages/blog/mui-x-v8-alpha-zero.md diff --git a/docs/pages/blog/mui-x-v8-alpha-zero.js b/docs/pages/blog/mui-x-v8-alpha-zero.js new file mode 100644 index 00000000000000..18973d9dfc7b32 --- /dev/null +++ b/docs/pages/blog/mui-x-v8-alpha-zero.js @@ -0,0 +1,7 @@ +import * as React from 'react'; +import TopLayoutBlog from 'docs/src/modules/components/TopLayoutBlog'; +import { docs } from './mui-x-v8-alpha-zero.md?muiMarkdown'; + +export default function Page() { + return ; +} diff --git a/docs/pages/blog/mui-x-v8-alpha-zero.md b/docs/pages/blog/mui-x-v8-alpha-zero.md new file mode 100644 index 00000000000000..2b547337a539c6 --- /dev/null +++ b/docs/pages/blog/mui-x-v8-alpha-zero.md @@ -0,0 +1,99 @@ +--- +title: The road to MUI X v8 +description: Explore the planned features and our roadmap to the next major version. +date: 2024-11-20T00:00:00.000Z +authors: ['josefreitas'] +tags: ['MUI X', 'Product'] +--- + +We're kicking off the development of [MUI X v8](https://github.com/mui/mui-x/releases/tag/v8.0.0-alpha.0). +Following our yearly release cycle, the target for the first stable release is March 2025. +This major update includes new versions of the Data Grid, Charts, Tree View, and the Date and Time Pickers. +We're excited to share our roadmap with you and invite you to join us on this journey! + +:::warning +Only MUI X is getting a new version—Material UI will remain in v6 for now. +Since only MUI X is getting a new version, you can rest assured that all MUI X v8 components will be fully compatible with Material UI v5 and v6. +:::: + +## What's the plan to get to the next major release? + +Before the official release of MUI X v8, we'll go through a few months of pre-releases. +During this period, we'll continue with our usual weekly release process and follow [semantic versioning](https://semver.org/). +While we'll still release bug fixes for v7, these will become less frequent as we progress toward a stable v8 release. +Our primary focus will be on delivering the new features and implementing the necessary breaking changes in the v8 pre-release packages. + +In the alpha phase, we'll introduce all planned breaking changes for this major version. Some APIs may be unstable—not in terms of functionality, but there may be adjustments or renaming of parameters. This phase is expected to last about two to three months. + +Following the alpha phase, the beta phase will focus on stabilizing the APIs, fixing bugs, and refining the overall experience. This phase is anticipated to take about one month. + +Finally, we'll release the first `v8.0.0` stable by March 2025, and we'll continue improving the components and adding features, but without making any new breaking changes until the next major version. + +## What happens to v7? + +During v8 pre-releases, v7 will continue to be the official current major, and it will remain supported during this time. +However, we will only release new v7 versions as needed to patch bugs or add community contributions. + +All new features and enhancements will go to v8, and after its first stable release, v7 will officially transition to [long-term support](https://mui.com/x/introduction/support/#long-term-support-lts) status. + +## Where's the v8 documentation? + +As mentioned above, v7 is still the official version, so by default, the documentation shows v7 features and API. +The next version's documentation is in the `v8` subdomain. + +- [https://next.mui.com/x/introduction/](https://next.mui.com/x/introduction/) + +## What's new in v8 + +The following is a list of enhancements in the pipeline for v8. +It contains the highlights we aim to include in the first versions: + +### Data Grid + +- [Drag and drop with touch support](https://github.com/mui/mui-x/issues/15385) +- [New Toolbar](https://github.com/mui/mui-x/issues/11584) +- [Row spanning](https://mui.com/x/react-data-grid/row-spanning/) (Now stable) +- [Pivoting](https://github.com/mui/mui-x/issues/214) [](/x/introduction/licensing/#premium-plan 'Premium plan') + +### Date and Time Pickers + +- [Improved visual customization](https://github.com/mui/mui-x/issues/14753) +- [Accessible DOM field by default](https://mui.com/x/react-date-pickers/fields/#accessible-dom-structure) +- [Time Range Picker](https://github.com/mui/mui-x/issues/4460) [](/x/introduction/licensing/#pro-plan 'Pro plan') + +### Tree View + +- [Parent/chidren selection propagation](https://github.com/mui/mui-x/issues/12883) +- [Lazy loading](https://github.com/mui/mui-x/issues/9687)[](/x/introduction/licensing/#pro-plan 'Pro plan') +- [Virtualization](https://github.com/mui/mui-x/issues/9685)[](/x/introduction/licensing/#pro-plan 'Pro plan') + +### Charts + +- Improved design +- [Radar Chart](https://github.com/mui/mui-x/issues/7925) +- [Improved data zoom](https://github.com/mui/mui-x/issues/15383)[](/x/introduction/licensing/#pro-plan 'Pro plan') +- [Funnel Chart](https://github.com/mui/mui-x/issues/7929)[](/x/introduction/licensing/#pro-plan 'Pro plan') + +:::info +You can check our [roadmap](https://github.com/orgs/mui/projects/35) for the full live list. +::: + +## How to migrate + +As usual, we've prepared a migration guide for each component, and we'll continuously update them as we make any breaking changes during the pre-releases. +They list every breaking change you may need to update to migrate your codebase. + +- [Data Grid](https://next.mui.com/x/migration/migration-data-grid-v7/) +- [Date and Time Pickers](https://next.mui.com/x/migration/migration-pickers-v7/) +- [Charts](https://next.mui.com/x/migration/migration-charts-v7/) +- [Tree View](https://next.mui.com/x/migration/migration-tree-view-v7/) + +We strongly encourage you to try the new version—it builds on the solid foundation we established with v7, bringing even more improvements! + +## How to get involved + +We'd love to hear about your expectations and pain points! Please consider [connecting with us](https://forms.gle/vsBv6CLPz9h57xg8A) for a user interview. +You'll get an insider's perspective on the development, and you'll be able to help us iterate early on the new features. + +We're also happy to receive feedback on new features and bug reports in our [GitHub repository](https://github.com/mui/mui-x/issues/new/choose). +You can follow every step of the v8 development process through our [changelog](https://github.com/mui/mui-x/releases). From 3251c3a0786e651372c4be7bb035585a60a7f06d Mon Sep 17 00:00:00 2001 From: sai chand <60743144+sai6855@users.noreply.github.com> Date: Thu, 14 Nov 2024 23:09:05 +0530 Subject: [PATCH 03/14] [materia-ui][StepIcon] Add SvgIconOwnProps type to StepIcon props (#44337) --- docs/pages/material-ui/api/step-icon.json | 2 +- packages/mui-material/src/StepIcon/StepIcon.d.ts | 7 +++++-- packages/mui-material/src/StepIcon/StepIcon.spec.tsx | 5 +++++ packages/mui-material/src/StepIcon/StepIcon.test.js | 3 ++- 4 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 packages/mui-material/src/StepIcon/StepIcon.spec.tsx diff --git a/docs/pages/material-ui/api/step-icon.json b/docs/pages/material-ui/api/step-icon.json index 82d908380447bb..16d31b1020e608 100644 --- a/docs/pages/material-ui/api/step-icon.json +++ b/docs/pages/material-ui/api/step-icon.json @@ -55,7 +55,7 @@ "muiName": "MuiStepIcon", "forwardsRefTo": "SVGSVGElement", "filename": "/packages/mui-material/src/StepIcon/StepIcon.js", - "inheritance": null, + "inheritance": { "component": "SvgIcon", "pathname": "/material-ui/api/svg-icon/" }, "demos": "", "cssComponent": false } diff --git a/packages/mui-material/src/StepIcon/StepIcon.d.ts b/packages/mui-material/src/StepIcon/StepIcon.d.ts index d71906a033977e..eae78f0f3fcc14 100644 --- a/packages/mui-material/src/StepIcon/StepIcon.d.ts +++ b/packages/mui-material/src/StepIcon/StepIcon.d.ts @@ -1,11 +1,13 @@ import * as React from 'react'; import { SxProps } from '@mui/system'; -import { InternalStandardProps as StandardProps } from '..'; +import { InternalStandardProps as StandardProps, SvgIconOwnProps } from '..'; import { Theme } from '../styles'; import { StepIconClasses } from './stepIconClasses'; export interface StepIconProps - extends StandardProps, 'children'> { + // TODO v7: extend React.HTMLAttributes as svg is root component of StepIcon not div + extends StandardProps, 'color' | 'children'>, + Omit { /** * Whether this step is active. * @default false @@ -46,5 +48,6 @@ export type StepIconClasskey = keyof NonNullable; * API: * * - [StepIcon API](https://mui.com/material-ui/api/step-icon/) + * - inherits [SvgIcon API](https://mui.com/material-ui/api/svg-icon/) */ export default function StepIcon(props: StepIconProps): React.JSX.Element; diff --git a/packages/mui-material/src/StepIcon/StepIcon.spec.tsx b/packages/mui-material/src/StepIcon/StepIcon.spec.tsx new file mode 100644 index 00000000000000..3a43cba9d79655 --- /dev/null +++ b/packages/mui-material/src/StepIcon/StepIcon.spec.tsx @@ -0,0 +1,5 @@ +import * as React from 'react'; +import StepIcon from '@mui/material/StepIcon'; + +icon} />; +icon} titleAccess="title" />; diff --git a/packages/mui-material/src/StepIcon/StepIcon.test.js b/packages/mui-material/src/StepIcon/StepIcon.test.js index 1469588b5bba7c..e4e0f7202545e4 100644 --- a/packages/mui-material/src/StepIcon/StepIcon.test.js +++ b/packages/mui-material/src/StepIcon/StepIcon.test.js @@ -2,6 +2,7 @@ import * as React from 'react'; import { expect } from 'chai'; import { createRenderer } from '@mui/internal-test-utils'; import StepIcon, { stepIconClasses as classes } from '@mui/material/StepIcon'; +import SvgIcon from '@mui/material/SvgIcon'; import describeConformance from '../../test/describeConformance'; describe('', () => { @@ -9,7 +10,7 @@ describe('', () => { describeConformance(, () => ({ classes, - inheritComponent: 'svg', + inheritComponent: SvgIcon, render, muiName: 'MuiStepIcon', testVariantProps: { completed: true }, From 016acabc5aeeeb57763854960413faa19b0d9bb4 Mon Sep 17 00:00:00 2001 From: Siriwat K Date: Fri, 15 Nov 2024 14:07:16 +0700 Subject: [PATCH 04/14] [system] Warn when calling `setMode` without configuring `colorSchemeSelector` (#43783) --- .../src/styles/ThemeProviderWithVars.test.js | 52 ++++++++++++++++++- .../src/cssVars/createCssVarsProvider.js | 17 +++++- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/packages/mui-material/src/styles/ThemeProviderWithVars.test.js b/packages/mui-material/src/styles/ThemeProviderWithVars.test.js index 6311728b415ca3..57cc558313c691 100644 --- a/packages/mui-material/src/styles/ThemeProviderWithVars.test.js +++ b/packages/mui-material/src/styles/ThemeProviderWithVars.test.js @@ -1,8 +1,15 @@ import * as React from 'react'; import { expect } from 'chai'; -import { createRenderer, screen } from '@mui/internal-test-utils'; +import { createRenderer, screen, fireEvent } from '@mui/internal-test-utils'; import Box from '@mui/material/Box'; -import { CssVarsProvider, extendTheme, useTheme } from '@mui/material/styles'; +import { + CssVarsProvider, + extendTheme, + useTheme, + ThemeProvider, + createTheme, + useColorScheme, +} from '@mui/material/styles'; describe('[Material UI] ThemeProviderWithVars', () => { let originalMatchmedia; @@ -360,4 +367,45 @@ describe('[Material UI] ThemeProviderWithVars', () => { borderBottomRightRadius: '16px', }); }); + + it('warns when using `setMode` without configuring `colorSchemeSelector`', () => { + function Test() { + const { setMode } = useColorScheme(); + return ; + } + render( + + + , + ); + + expect(() => { + fireEvent.click(screen.getByText('Dark')); + }).toErrorDev([ + 'MUI: The `setMode` function has no effect if `colorSchemeSelector` is `media` (`media` is the default value).\nTo toggle the mode manually, please configure `colorSchemeSelector` to use a class or data attribute.\nTo learn more, visit https://mui.com/material-ui/customization/css-theme-variables/configuration/#toggling-dark-mode-manually', + ]); + }); + + it('do not warn when using `setMode` with `colorSchemeSelector` that is not `media`', () => { + function Test() { + const { setMode } = useColorScheme(); + return ; + } + render( + + + , + ); + + expect(() => { + fireEvent.click(screen.getByText('Dark')); + }).not.toErrorDev(); + }); }); diff --git a/packages/mui-system/src/cssVars/createCssVarsProvider.js b/packages/mui-system/src/cssVars/createCssVarsProvider.js index 9b521128ec13ab..cfed67e92e4f33 100644 --- a/packages/mui-system/src/cssVars/createCssVarsProvider.js +++ b/packages/mui-system/src/cssVars/createCssVarsProvider.js @@ -242,7 +242,21 @@ export default function createCssVarsProvider(options) { lightColorScheme, mode, setColorScheme, - setMode, + setMode: + process.env.NODE_ENV === 'production' + ? setMode + : (newMode) => { + if (theme.colorSchemeSelector === 'media') { + console.error( + [ + 'MUI: The `setMode` function has no effect if `colorSchemeSelector` is `media` (`media` is the default value).', + 'To toggle the mode manually, please configure `colorSchemeSelector` to use a class or data attribute.', + 'To learn more, visit https://mui.com/material-ui/customization/css-theme-variables/configuration/#toggling-dark-mode-manually', + ].join('\n'), + ); + } + setMode(newMode); + }, systemMode, }), [ @@ -254,6 +268,7 @@ export default function createCssVarsProvider(options) { setColorScheme, setMode, systemMode, + theme.colorSchemeSelector, ], ); From f2cfee3316d22c8f7bda86a6cba39ade226e30b2 Mon Sep 17 00:00:00 2001 From: Jose C Quintas Jr Date: Fri, 15 Nov 2024 09:18:02 +0100 Subject: [PATCH 05/14] [code-infra] Use vitest-compatible skip in `describeConformance` (#44412) --- packages-internal/test-utils/src/describeConformance.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages-internal/test-utils/src/describeConformance.tsx b/packages-internal/test-utils/src/describeConformance.tsx index e3625ea577ff73..64c5600dad12c1 100644 --- a/packages-internal/test-utils/src/describeConformance.tsx +++ b/packages-internal/test-utils/src/describeConformance.tsx @@ -617,12 +617,14 @@ function testThemeDefaultProps( }); describe('default props provider:', () => { - it('respect custom default props', async function test() { + it('respect custom default props', async function test(t = {}) { const testProp = 'data-id'; const { muiName, render, DefaultPropsProvider } = getOptions(); if (!DefaultPropsProvider) { - this.skip(); + // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + this?.skip?.() ?? t?.skip(); } if (!muiName) { @@ -634,6 +636,7 @@ function testThemeDefaultProps( } const { container } = await render( + // @ts-expect-error we skip it above. Date: Fri, 15 Nov 2024 13:48:55 +0100 Subject: [PATCH 06/14] [blog] Fix reference to subdomain on MUI X v8 alpha zero post (#44416) --- docs/pages/blog/mui-x-v8-alpha-zero.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/blog/mui-x-v8-alpha-zero.md b/docs/pages/blog/mui-x-v8-alpha-zero.md index 2b547337a539c6..74d875d215be2e 100644 --- a/docs/pages/blog/mui-x-v8-alpha-zero.md +++ b/docs/pages/blog/mui-x-v8-alpha-zero.md @@ -39,7 +39,7 @@ All new features and enhancements will go to v8, and after its first stable rele ## Where's the v8 documentation? As mentioned above, v7 is still the official version, so by default, the documentation shows v7 features and API. -The next version's documentation is in the `v8` subdomain. +The next version's documentation is in the `next` subdomain. - [https://next.mui.com/x/introduction/](https://next.mui.com/x/introduction/) From 81337b29da3d4d34cd3b187c9b174efa8a97dd4b Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Fri, 15 Nov 2024 14:01:30 +0100 Subject: [PATCH 07/14] [website] Fix Pro SVG icon Regression introduced in #44374. --- docs/public/static/branding/pricing/x-plan-pro.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/public/static/branding/pricing/x-plan-pro.svg b/docs/public/static/branding/pricing/x-plan-pro.svg index cec6124bb4ef2f..8f8f149dd754d0 100644 --- a/docs/public/static/branding/pricing/x-plan-pro.svg +++ b/docs/public/static/branding/pricing/x-plan-pro.svg @@ -1 +1 @@ - \ No newline at end of file + From 2224b22927a4858551890cda26b9dd27adb7101f Mon Sep 17 00:00:00 2001 From: Jose C Quintas Jr Date: Fri, 15 Nov 2024 16:01:47 +0100 Subject: [PATCH 08/14] [utils] Add documentation to `useForkRef` (#44410) --- .../mui-utils/src/useForkRef/useForkRef.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/packages/mui-utils/src/useForkRef/useForkRef.ts b/packages/mui-utils/src/useForkRef/useForkRef.ts index f2a3c4e74abc4c..e4fd69ecb94a46 100644 --- a/packages/mui-utils/src/useForkRef/useForkRef.ts +++ b/packages/mui-utils/src/useForkRef/useForkRef.ts @@ -2,6 +2,25 @@ import * as React from 'react'; import setRef from '../setRef'; +/** + * Takes an array of refs and returns a new ref which will apply any modification to all of the refs. + * + * This is useful when you want have the ref used in multiple places. + * + * ```tsx + * const newRef = React.useRef(null); + * const refFork = useForkRef(newRef, props.ref); + * + * return ( + * + * + * + * ); + * ``` + * + * @param {Array | undefined>} refs the ref array. + * @returns {React.RefCallback | null} the new ref callback. + */ export default function useForkRef( ...refs: Array | undefined> ): React.RefCallback | null { From e8e4b79b557ec85d5ff46d53ce1f1f5a5347dc16 Mon Sep 17 00:00:00 2001 From: Diego Andai Date: Fri, 15 Nov 2024 12:25:50 -0300 Subject: [PATCH 09/14] [material-ui][Autocomplete] Use `ul` element for the listbox (#44422) --- packages/mui-material/src/Autocomplete/Autocomplete.js | 2 +- packages/mui-material/src/Autocomplete/Autocomplete.test.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mui-material/src/Autocomplete/Autocomplete.js b/packages/mui-material/src/Autocomplete/Autocomplete.js index f249219d26da5e..ff70335f6f0986 100644 --- a/packages/mui-material/src/Autocomplete/Autocomplete.js +++ b/packages/mui-material/src/Autocomplete/Autocomplete.js @@ -326,7 +326,7 @@ const AutocompleteNoOptions = styled('div', { })), ); -const AutocompleteListbox = styled('div', { +const AutocompleteListbox = styled('ul', { name: 'MuiAutocomplete', slot: 'Listbox', overridesResolver: (props, styles) => styles.listbox, diff --git a/packages/mui-material/src/Autocomplete/Autocomplete.test.js b/packages/mui-material/src/Autocomplete/Autocomplete.test.js index 97099aa953faee..181fdf378d2bc9 100644 --- a/packages/mui-material/src/Autocomplete/Autocomplete.test.js +++ b/packages/mui-material/src/Autocomplete/Autocomplete.test.js @@ -1069,6 +1069,7 @@ describe('', () => { expect(textbox).to.have.attribute('aria-expanded', 'true'); const listbox = getByRole('listbox'); + expect(listbox.tagName.toLowerCase()).to.equal('ul'); expect(textbox).to.have.attribute('aria-controls', listbox.getAttribute('id')); expect(textbox, 'no option is focused when opened').not.to.have.attribute( 'aria-activedescendant', From 4e26c0b003eaca35937e8e0df446ac89e37b57f0 Mon Sep 17 00:00:00 2001 From: Diego Andai Date: Fri, 15 Nov 2024 12:32:52 -0300 Subject: [PATCH 10/14] [docs][material-ui][Autocomplete] Fix virtualization demo (#44382) --- .../components/autocomplete/Virtualize.js | 6 +- .../components/autocomplete/Virtualize.tsx | 6 +- .../autocomplete/Virtualize.tsx.preview | 15 -- pnpm-lock.yaml | 3 + test/package.json | 1 + .../fixtures/Autocomplete/Virtualize.js | 162 ++++++++++++++++++ test/regressions/index.test.js | 10 ++ 7 files changed, 186 insertions(+), 17 deletions(-) delete mode 100644 docs/data/material/components/autocomplete/Virtualize.tsx.preview create mode 100644 test/regressions/fixtures/Autocomplete/Virtualize.js diff --git a/docs/data/material/components/autocomplete/Virtualize.js b/docs/data/material/components/autocomplete/Virtualize.js index 72c0cfa455bc3e..ca70916330891d 100644 --- a/docs/data/material/components/autocomplete/Virtualize.js +++ b/docs/data/material/components/autocomplete/Virtualize.js @@ -149,7 +149,11 @@ export default function Virtualize() { renderGroup={(params) => params} slots={{ popper: StyledPopper, - listbox: ListboxComponent, + }} + slotProps={{ + listbox: { + component: ListboxComponent, + }, }} /> ); diff --git a/docs/data/material/components/autocomplete/Virtualize.tsx b/docs/data/material/components/autocomplete/Virtualize.tsx index 11440cf0be8ec3..e2d8923bc3d116 100644 --- a/docs/data/material/components/autocomplete/Virtualize.tsx +++ b/docs/data/material/components/autocomplete/Virtualize.tsx @@ -155,7 +155,11 @@ export default function Virtualize() { renderGroup={(params) => params as any} slots={{ popper: StyledPopper, - listbox: ListboxComponent, + }} + slotProps={{ + listbox: { + component: ListboxComponent, + }, }} /> ); diff --git a/docs/data/material/components/autocomplete/Virtualize.tsx.preview b/docs/data/material/components/autocomplete/Virtualize.tsx.preview deleted file mode 100644 index d8b7f0e136c084..00000000000000 --- a/docs/data/material/components/autocomplete/Virtualize.tsx.preview +++ /dev/null @@ -1,15 +0,0 @@ - option[0].toUpperCase()} - renderInput={(params) => } - renderOption={(props, option, state) => - [props, option, state.index] as React.ReactNode - } - renderGroup={(params) => params as any} - slots={{ - popper: StyledPopper, - listbox: ListboxComponent, - }} -/> \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1c623912a212f..5828da74b8d1d8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2349,6 +2349,9 @@ importers: react-router-dom: specifier: ^6.28.0 version: 6.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react-window: + specifier: ^1.8.10 + version: 1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) sinon: specifier: ^19.0.2 version: 19.0.2 diff --git a/test/package.json b/test/package.json index 7e0ca66fbfd11a..195ad9f99ef456 100644 --- a/test/package.json +++ b/test/package.json @@ -35,6 +35,7 @@ "react-dom": "^18.3.1", "react-is": "^18.3.1", "react-router-dom": "^6.28.0", + "react-window": "^1.8.10", "sinon": "^19.0.2", "styled-components": "^6.1.13", "stylis": "4.2.0", diff --git a/test/regressions/fixtures/Autocomplete/Virtualize.js b/test/regressions/fixtures/Autocomplete/Virtualize.js new file mode 100644 index 00000000000000..cc3f1a9064f218 --- /dev/null +++ b/test/regressions/fixtures/Autocomplete/Virtualize.js @@ -0,0 +1,162 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import TextField from '@mui/material/TextField'; +import Autocomplete, { autocompleteClasses } from '@mui/material/Autocomplete'; +import useMediaQuery from '@mui/material/useMediaQuery'; +import ListSubheader from '@mui/material/ListSubheader'; +import Popper from '@mui/material/Popper'; +import { useTheme, styled } from '@mui/material/styles'; +import { VariableSizeList } from 'react-window'; +import Typography from '@mui/material/Typography'; + +const LISTBOX_PADDING = 8; // px + +function renderRow(props) { + const { data, index, style } = props; + const dataSet = data[index]; + const inlineStyle = { + ...style, + top: style.top + LISTBOX_PADDING, + }; + + if (dataSet.hasOwnProperty('group')) { + return ( + + {dataSet.group} + + ); + } + + const { key, ...optionProps } = dataSet[0]; + + return ( + + {`#${dataSet[2] + 1} - ${dataSet[1]}`} + + ); +} + +const OuterElementContext = React.createContext({}); + +const OuterElementType = React.forwardRef((props, ref) => { + const outerProps = React.useContext(OuterElementContext); + return
; +}); + +function useResetCache(data) { + const ref = React.useRef(null); + React.useEffect(() => { + if (ref.current != null) { + ref.current.resetAfterIndex(0, true); + } + }, [data]); + return ref; +} + +// Adapter for react-window +const ListboxComponent = React.forwardRef(function ListboxComponent(props, ref) { + const { children, ...other } = props; + const itemData = []; + children.forEach((item) => { + itemData.push(item); + itemData.push(...(item.children || [])); + }); + + const theme = useTheme(); + const smUp = useMediaQuery(theme.breakpoints.up('sm'), { + noSsr: true, + }); + const itemCount = itemData.length; + const itemSize = smUp ? 36 : 48; + + const getChildSize = (child) => { + if (child.hasOwnProperty('group')) { + return 48; + } + + return itemSize; + }; + + const getHeight = () => { + if (itemCount > 8) { + return 8 * itemSize; + } + return itemData.map(getChildSize).reduce((a, b) => a + b, 0); + }; + + const gridRef = useResetCache(itemCount); + + return ( +
+ + getChildSize(itemData[index])} + overscanCount={5} + itemCount={itemCount} + > + {renderRow} + + +
+ ); +}); + +ListboxComponent.propTypes = { + children: PropTypes.node, +}; + +function random(length) { + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + + for (let i = 0; i < length; i += 1) { + result += characters.charAt(Math.floor(Math.random() * characters.length)); + } + + return result; +} + +const StyledPopper = styled(Popper)({ + [`& .${autocompleteClasses.listbox}`]: { + boxSizing: 'border-box', + '& ul': { + padding: 0, + margin: 0, + }, + }, +}); + +const OPTIONS = Array.from(new Array(10000)) + .map(() => random(10 + Math.ceil(Math.random() * 20))) + .sort((a, b) => a.toUpperCase().localeCompare(b.toUpperCase())); + +export default function Virtualize() { + return ( +
+ option[0].toUpperCase()} + renderInput={(params) => } + renderOption={(props, option, state) => [props, option, state.index]} + renderGroup={(params) => params} + slots={{ + popper: StyledPopper, + }} + slotProps={{ + listbox: { + component: ListboxComponent, + }, + }} + /> +
+ ); +} diff --git a/test/regressions/index.test.js b/test/regressions/index.test.js index 290b89661556b1..7eb53f2887632d 100644 --- a/test/regressions/index.test.js +++ b/test/regressions/index.test.js @@ -144,6 +144,16 @@ async function main() { route: '/regression-Autocomplete/TextboxExpandsOnListboxOpen2', }); }); + + it('should style virtualized listbox correctly', async () => { + const testcase = await renderFixture('/regression-Autocomplete/Virtualize'); + await page.getByRole('combobox').click(); + await takeScreenshot({ testcase, route: '/regression-Autocomplete/Virtualize2' }); + await page.hover('[role="option"]'); + await takeScreenshot({ testcase, route: '/regression-Autocomplete/Virtualize3' }); + await page.click('[role="option"]'); + await takeScreenshot({ testcase, route: '/regression-Autocomplete/Virtualize4' }); + }); }); }); From c7e3f8f46832478e7d06363b489d7cde80f3f67a Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Fri, 15 Nov 2024 18:52:36 +0100 Subject: [PATCH 11/14] [core] Polish useForkRef docs (#44424) --- packages/mui-utils/src/useForkRef/useForkRef.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/mui-utils/src/useForkRef/useForkRef.ts b/packages/mui-utils/src/useForkRef/useForkRef.ts index e4fd69ecb94a46..521c97d3f93d85 100644 --- a/packages/mui-utils/src/useForkRef/useForkRef.ts +++ b/packages/mui-utils/src/useForkRef/useForkRef.ts @@ -4,22 +4,19 @@ import setRef from '../setRef'; /** * Takes an array of refs and returns a new ref which will apply any modification to all of the refs. - * - * This is useful when you want have the ref used in multiple places. + * This is useful when you want to have the ref used in multiple places. * * ```tsx - * const newRef = React.useRef(null); - * const refFork = useForkRef(newRef, props.ref); + * const rootRef = React.useRef(null); + * const refFork = useForkRef(rootRef, props.ref); * * return ( - * - * - * + * * ); * ``` * - * @param {Array | undefined>} refs the ref array. - * @returns {React.RefCallback | null} the new ref callback. + * @param {Array | undefined>} refs The ref array. + * @returns {React.RefCallback | null} The new ref callback. */ export default function useForkRef( ...refs: Array | undefined> From a0ffee42815b110e14107249f193b7505d1761e5 Mon Sep 17 00:00:00 2001 From: Diego Andai Date: Fri, 15 Nov 2024 14:59:27 -0300 Subject: [PATCH 12/14] [docs] Bring back `*Component` and `*Props` codemods and deprecation messages (#44383) --- .../migrating-from-deprecated-apis.md | 158 ++++++++++++++++++ docs/pages/material-ui/api/accordion.json | 12 +- docs/pages/material-ui/api/autocomplete.json | 33 +++- docs/pages/material-ui/api/avatar.json | 6 +- docs/pages/material-ui/api/backdrop.json | 7 +- docs/pages/material-ui/api/speed-dial.json | 13 +- docs/pages/material-ui/api/step-label.json | 12 +- packages/mui-codemod/README.md | 14 +- .../src/deprecations/all/deprecations-all.js | 6 + .../autocomplete-props/autocomplete-props.js | 145 ++++++++++++++++ .../autocomplete-props/test-cases/actual.js | 23 +++ .../autocomplete-props/test-cases/expected.js | 44 ++++- .../test-cases/theme.actual.js | 10 ++ .../test-cases/theme.expected.js | 25 ++- .../backdrop-props/backdrop-props.js | 8 + .../backdrop-props/test-cases/actual.js | 25 +++ .../backdrop-props/test-cases/expected.js | 25 +++ .../backdrop-props/test-cases/theme.actual.js | 31 ++++ .../test-cases/theme.expected.js | 32 ++++ .../step-label-props/step-label-props.js | 16 ++ .../step-label-props/test-cases/actual.js | 12 ++ .../step-label-props/test-cases/expected.js | 26 +++ .../test-cases/theme.actual.js | 20 +++ .../test-cases/theme.expected.js | 33 ++++ .../mui-material/src/Accordion/Accordion.d.ts | 2 + .../mui-material/src/Accordion/Accordion.js | 2 + .../src/Autocomplete/Autocomplete.d.ts | 5 + .../src/Autocomplete/Autocomplete.js | 5 + packages/mui-material/src/Avatar/Avatar.d.ts | 1 + packages/mui-material/src/Avatar/Avatar.js | 1 + .../mui-material/src/Backdrop/Backdrop.d.ts | 1 + .../mui-material/src/Backdrop/Backdrop.js | 1 + .../mui-material/src/SpeedDial/SpeedDial.d.ts | 2 + .../mui-material/src/SpeedDial/SpeedDial.js | 2 + .../mui-material/src/StepLabel/StepLabel.d.ts | 2 + .../mui-material/src/StepLabel/StepLabel.js | 2 + 36 files changed, 739 insertions(+), 23 deletions(-) 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 ee033608634f79..e59a553b13259d 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 @@ -87,6 +87,36 @@ You can also manually update your theme as shown in the snippet below: This reduces the API surface and lets you define variants in other slots of the component. +## Accordion + +Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#accordion-props) below to migrate the code as described in the following sections: + +```bash +npx @mui/codemod@latest deprecations/accordion-props +``` + +### TransitionComponent + +The Accordion's `TransitionComponent` prop was deprecated in favor of `slots.transition`: + +```diff + +``` + +### TransitionProps + +The Accordion's `TransitionProps` prop was deprecated in favor of `slotProps.transition`: + +```diff + +``` + ## AccordionSummary Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#accordion-summary-classes) below to migrate the code as described in the following sections: @@ -251,6 +281,47 @@ Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-code npx @mui/codemod@latest deprecations/autocomplete-props ``` +### \*Component props + +All of the Autocomplete's slot (`*Component`) props were deprecated in favor of equivalent `slots` and `slotProps` entries: + +```diff + +``` + +:::warning +The listbox slot is a special case because `ListboxComponent` was implemented differently from the other `*Component` props, behaving similar to the `component` and `as` props. +The `slots.listbox` entry exists and you can use it to replace the component entirely, but if you want to keep `ListboxComponent`'s behavior which maintains the original listbox styles, you should use the `slotProps.listbox.component` entry. +::: + +### \*Props props + +All of the Autocomplete's slot props (`*Props`) props were deprecated in favor of equivalent `slotProps` entries: + +```diff + +``` + ### componentsProps The Autocomplete's `componentsProps` prop was deprecated in favor of `slotProps`: @@ -271,6 +342,32 @@ The Autocomplete's `componentsProps` prop was deprecated in favor of `slotProps` /> ``` +## Avatar + +Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#avatar-props) below to migrate the code as described in the following sections: + +```bash +npx @mui/codemod@latest deprecations/avatar-props +``` + +### imgProps + +The Avatar's `imgProps` prop was deprecated in favor of `slotProps.img`: + +```diff + {}, +- onLoad: () => {}, ++ slotProps={{ ++ img: { ++ onError: () => {}, ++ onLoad: () => {}, ++ } + }} + />; +``` + ## AvatarGroup Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#avatar-group-props) below to migrate the code as described in the following sections: @@ -359,6 +456,16 @@ The Backdrop's `componentsProps` prop was deprecated in favor of `slotProps`: /> ``` +### TransitionComponent + +The Backdrop's `TransitionComponent` prop was deprecated in favor of `slots.transition`: + +```diff + ``` +### StepIconComponent + +The StepLabel's `StepIconComponent` prop was deprecated in favor of `slots.stepIcon`: + +```diff + +``` + +### StepIconProps + +The StepLabel's `StepIconProps` prop was deprecated in favor of `slotProps.stepIcon`: + +```diff + +``` + ## StepConnector Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#step-connector-classes) below to migrate the code as described in the following sections: @@ -1664,3 +1793,32 @@ Here's how to migrate: }, }, ``` + +## SpeedDial + +Use the [codemod](https://github.com/mui/material-ui/tree/HEAD/packages/mui-codemod#speed-dial-props) below to migrate the code as described in the following sections: + +```bash +npx @mui/codemod@next deprecations/speed-dial-props +``` + +### TransitionComponent + +The SpeedDial's `TransitionComponent` prop was deprecated in favor of `slots.transition`: + +```diff + +``` diff --git a/docs/pages/material-ui/api/accordion.json b/docs/pages/material-ui/api/accordion.json index c1025809a0aa7b..2120b8585e77e7 100644 --- a/docs/pages/material-ui/api/accordion.json +++ b/docs/pages/material-ui/api/accordion.json @@ -35,8 +35,16 @@ }, "additionalInfo": { "sx": true } }, - "TransitionComponent": { "type": { "name": "elementType" } }, - "TransitionProps": { "type": { "name": "object" } } + "TransitionComponent": { + "type": { "name": "elementType" }, + "deprecated": true, + "deprecationInfo": "Use slots.transition instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, + "TransitionProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use slotProps.transition instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + } }, "name": "Accordion", "imports": [ diff --git a/docs/pages/material-ui/api/autocomplete.json b/docs/pages/material-ui/api/autocomplete.json index 0eebdc3261a28d..b61f4c3c93fdaa 100644 --- a/docs/pages/material-ui/api/autocomplete.json +++ b/docs/pages/material-ui/api/autocomplete.json @@ -16,7 +16,11 @@ }, "default": "false" }, - "ChipProps": { "type": { "name": "object" } }, + "ChipProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use slotProps.chip instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "clearIcon": { "type": { "name": "node" }, "default": "" }, "clearOnBlur": { "type": { "name": "bool" }, "default": "!props.freeSolo" }, @@ -93,8 +97,17 @@ } }, "limitTags": { "type": { "name": "custom", "description": "integer" }, "default": "-1" }, - "ListboxComponent": { "type": { "name": "elementType" }, "default": "'ul'" }, - "ListboxProps": { "type": { "name": "object" } }, + "ListboxComponent": { + "type": { "name": "elementType" }, + "default": "'ul'", + "deprecated": true, + "deprecationInfo": "Use slotProps.listbox.component instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, + "ListboxProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use slotProps.listbox instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "loading": { "type": { "name": "bool" }, "default": "false" }, "loadingText": { "type": { "name": "node" }, "default": "'Loading…'" }, "multiple": { "type": { "name": "bool" }, "default": "false" }, @@ -137,8 +150,18 @@ "open": { "type": { "name": "bool" } }, "openOnFocus": { "type": { "name": "bool" }, "default": "false" }, "openText": { "type": { "name": "string" }, "default": "'Open'" }, - "PaperComponent": { "type": { "name": "elementType" }, "default": "Paper" }, - "PopperComponent": { "type": { "name": "elementType" }, "default": "Popper" }, + "PaperComponent": { + "type": { "name": "elementType" }, + "default": "Paper", + "deprecated": true, + "deprecationInfo": "Use slots.paper instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, + "PopperComponent": { + "type": { "name": "elementType" }, + "default": "Popper", + "deprecated": true, + "deprecationInfo": "Use slots.popper instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "popupIcon": { "type": { "name": "node" }, "default": "" }, "readOnly": { "type": { "name": "bool" }, "default": "false" }, "renderGroup": { diff --git a/docs/pages/material-ui/api/avatar.json b/docs/pages/material-ui/api/avatar.json index c7049f61c281f4..ca3e4f30330a72 100644 --- a/docs/pages/material-ui/api/avatar.json +++ b/docs/pages/material-ui/api/avatar.json @@ -4,7 +4,11 @@ "children": { "type": { "name": "node" } }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, "component": { "type": { "name": "elementType" } }, - "imgProps": { "type": { "name": "object" } }, + "imgProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use slotProps.img instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "sizes": { "type": { "name": "string" } }, "slotProps": { "type": { "name": "shape", "description": "{ img?: func
| object }" }, diff --git a/docs/pages/material-ui/api/backdrop.json b/docs/pages/material-ui/api/backdrop.json index 591d41f1a66d8d..abf7ced24f3346 100644 --- a/docs/pages/material-ui/api/backdrop.json +++ b/docs/pages/material-ui/api/backdrop.json @@ -38,7 +38,12 @@ }, "additionalInfo": { "sx": true } }, - "TransitionComponent": { "type": { "name": "elementType" }, "default": "Fade" }, + "TransitionComponent": { + "type": { "name": "elementType" }, + "default": "Fade", + "deprecated": true, + "deprecationInfo": "Use slots.transition instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "transitionDuration": { "type": { "name": "union", diff --git a/docs/pages/material-ui/api/speed-dial.json b/docs/pages/material-ui/api/speed-dial.json index de5ec1866b4d4d..de7696ebdd9125 100644 --- a/docs/pages/material-ui/api/speed-dial.json +++ b/docs/pages/material-ui/api/speed-dial.json @@ -44,7 +44,12 @@ }, "additionalInfo": { "sx": true } }, - "TransitionComponent": { "type": { "name": "elementType" }, "default": "Zoom" }, + "TransitionComponent": { + "type": { "name": "elementType" }, + "default": "Zoom\n* @deprecated Use `slots.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/)", + "deprecated": true, + "deprecationInfo": "Use slots.transition instead. This prop will be removed in v7. How to migrate" + }, "transitionDuration": { "type": { "name": "union", @@ -52,7 +57,11 @@ }, "default": "{\n enter: theme.transitions.duration.enteringScreen,\n exit: theme.transitions.duration.leavingScreen,\n}" }, - "TransitionProps": { "type": { "name": "object" } } + "TransitionProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use slotProps.transition instead. This prop will be removed in v7. How to migrate" + } }, "name": "SpeedDial", "imports": [ diff --git a/docs/pages/material-ui/api/step-label.json b/docs/pages/material-ui/api/step-label.json index 50cf61702588a3..8c51868b91236d 100644 --- a/docs/pages/material-ui/api/step-label.json +++ b/docs/pages/material-ui/api/step-label.json @@ -22,8 +22,16 @@ "type": { "name": "shape", "description": "{ label?: elementType, stepIcon?: elementType }" }, "default": "{}" }, - "StepIconComponent": { "type": { "name": "elementType" } }, - "StepIconProps": { "type": { "name": "object" } }, + "StepIconComponent": { + "type": { "name": "elementType" }, + "deprecated": true, + "deprecationInfo": "Use slots.stepIcon instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, + "StepIconProps": { + "type": { "name": "object" }, + "deprecated": true, + "deprecationInfo": "Use slotProps.stepIcon instead. This prop will be removed in v7. See Migrating from deprecated APIs for more details." + }, "sx": { "type": { "name": "union", diff --git a/packages/mui-codemod/README.md b/packages/mui-codemod/README.md index 77c2dd3f137d77..7c65a8f0d7e0e3 100644 --- a/packages/mui-codemod/README.md +++ b/packages/mui-codemod/README.md @@ -275,12 +275,14 @@ npx @mui/codemod@latest deprecations/alert-props - }} + slots={{ + paper: CustomPaper, -+ popper: CustomPopper, -+ listbox: CustomListbox, ++ popper: CustomPopper + }} + slotProps={{ + chip: { height: 10 }, -+ listbox: { height: 12 }, ++ listbox: { ++ component: CustomListbox, ++ ...{ height: 12 }, ++ }, + clearIndicator: { width: 10 }, + paper: { width: 12 }, + popper: { width: 14 }, @@ -306,11 +308,13 @@ npx @mui/codemod@latest deprecations/alert-props + slots: { + paper: CustomPaper, + popper: CustomPopper, -+ listbox: CustomListbox, + }, + slotProps: { + chip: { height: 10 }, -+ listbox: { height: 12 }, ++ listbox: { ++ component: CustomListbox, ++ ...{ height: 12 }, ++ }, + clearIndicator: { width: 10 }, + paper: { width: 12 }, + popper: { width: 14 }, diff --git a/packages/mui-codemod/src/deprecations/all/deprecations-all.js b/packages/mui-codemod/src/deprecations/all/deprecations-all.js index c1dd70ef2392c4..eccb9e3d130375 100644 --- a/packages/mui-codemod/src/deprecations/all/deprecations-all.js +++ b/packages/mui-codemod/src/deprecations/all/deprecations-all.js @@ -1,7 +1,9 @@ import transformAccordionClasses from '../accordion-summary-classes'; +import transformAccordionProps from '../accordion-props'; import transformAlertClasses from '../alert-classes'; import transformAvatarGroupProps from '../avatar-group-props'; import transformAutocompleteProps from '../autocomplete-props'; +import transformAvatarProps from '../avatar-props'; import transformBackdropProps from '../backdrop-props'; import transformButtonClasses from '../button-classes'; import transformButtonGroupClasses from '../button-group-classes'; @@ -16,6 +18,7 @@ import transformInputProps from '../input-props'; import transformModalProps from '../modal-props'; import transformOutlinedInputProps from '../outlined-input-props'; import transformPaginationItemClasses from '../pagination-item-classes'; +import transformSpeedDialProps from '../speed-dial-props'; import transformTableSortLabelClasses from '../table-sort-label-classes'; import transformStepConnectorClasses from '../step-connector-classes'; import transformStepLabelProps from '../step-label-props'; @@ -29,9 +32,11 @@ import transformToggleButtonGroupClasses from '../toggle-button-group-classes'; */ export default function deprecationsAll(file, api, options) { file.source = transformAccordionClasses(file, api, options); + file.source = transformAccordionProps(file, api, options); file.source = transformAlertClasses(file, api, options); file.source = transformAvatarGroupProps(file, api, options); file.source = transformAutocompleteProps(file, api, options); + file.source = transformAvatarProps(file, api, options); file.source = transformBackdropProps(file, api, options); file.source = transformButtonClasses(file, api, options); file.source = transformButtonGroupClasses(file, api, options); @@ -46,6 +51,7 @@ export default function deprecationsAll(file, api, options) { file.source = transformModalProps(file, api, options); file.source = transformOutlinedInputProps(file, api, options); file.source = transformPaginationItemClasses(file, api, options); + file.source = transformSpeedDialProps(file, api, options); file.source = transformStepConnectorClasses(file, api, options); file.source = transformStepLabelProps(file, api, options); file.source = transformTableSortLabelClasses(file, api, options); 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 540bc4fa306a9e..6c43fb44c03306 100644 --- a/packages/mui-codemod/src/deprecations/autocomplete-props/autocomplete-props.js +++ b/packages/mui-codemod/src/deprecations/autocomplete-props/autocomplete-props.js @@ -1,4 +1,10 @@ +import movePropIntoSlots from '../utils/movePropIntoSlots'; +import movePropIntoSlotProps from '../utils/movePropIntoSlotProps'; import replaceComponentsWithSlots from '../utils/replaceComponentsWithSlots'; +import findComponentJSX from '../../util/findComponentJSX'; +import findComponentDefaultProps from '../../util/findComponentDefaultProps'; +import assignObject from '../../util/assignObject'; +import appendAttribute from '../../util/appendAttribute'; /** * @param {import('jscodeshift').FileInfo} file @@ -9,7 +15,146 @@ export default function transformer(file, api, options) { const root = j(file.source); const printOptions = options.printOptions; + movePropIntoSlots(j, { + root, + componentName: 'Autocomplete', + propName: 'PaperComponent', + slotName: 'paper', + }); + + movePropIntoSlots(j, { + root, + componentName: 'Autocomplete', + propName: 'PopperComponent', + slotName: 'popper', + }); + + movePropIntoSlotProps(j, { + root, + componentName: 'Autocomplete', + propName: 'ListboxProps', + slotName: 'listbox', + }); + + movePropIntoSlotProps(j, { + root, + componentName: 'Autocomplete', + propName: 'ChipProps', + slotName: 'chip', + }); + replaceComponentsWithSlots(j, { root, componentName: 'Autocomplete' }); + // Move ListboxComponent JSX prop into slotProps.listbox.component + findComponentJSX(j, { root, componentName: 'Autocomplete' }, (elementPath) => { + const element = elementPath.node; + const propIndex = element.openingElement.attributes.findIndex( + (attr) => attr.type === 'JSXAttribute' && attr.name.name === 'ListboxComponent', + ); + + if (propIndex !== -1) { + const removedValue = element.openingElement.attributes.splice(propIndex, 1)[0].value + .expression; + let hasSlotProps = false; + element.openingElement.attributes.forEach((attr) => { + if (attr.name?.name === 'slotProps') { + hasSlotProps = true; + const slots = attr.value.expression; + const slotIndex = slots.properties.findIndex((prop) => prop?.key?.name === 'listbox'); + if (slotIndex === -1) { + assignObject(j, { + target: attr, + key: 'listbox', + expression: j.objectExpression([ + j.objectProperty(j.identifier('component'), removedValue), + ]), + }); + } else { + const slotPropsSlotValue = slots.properties.splice(slotIndex, 1)[0].value; + assignObject(j, { + target: attr, + key: 'listbox', + expression: j.objectExpression([ + j.objectProperty(j.identifier('component'), removedValue), + j.spreadElement(slotPropsSlotValue), + ]), + }); + } + } + }); + + if (!hasSlotProps) { + appendAttribute(j, { + target: element, + attributeName: 'slotProps', + expression: j.objectExpression([ + j.objectProperty( + j.identifier('listbox'), + j.objectExpression([j.objectProperty(j.identifier('component'), removedValue)]), + ), + ]), + }); + } + } + }); + + // Move ListboxComponent default prop into slotProps.listbox.component + const defaultPropsPathCollection = findComponentDefaultProps(j, { + root, + componentName: 'Autocomplete', + }); + + defaultPropsPathCollection + .find(j.ObjectProperty, { key: { name: 'ListboxComponent' } }) + .forEach((path) => { + const removedValue = path.value.value; + const defaultProps = path.parent.value; + + let hasSlotProps = false; + defaultProps.properties.forEach((property) => { + if (property.key?.name === 'slotProps') { + hasSlotProps = true; + const slotIndex = property.value.properties.findIndex( + (prop) => prop?.key?.name === 'listbox', + ); + if (slotIndex === -1) { + property.value.properties.push( + j.objectProperty( + j.identifier('listbox'), + j.objectExpression([j.objectProperty(j.identifier('component'), removedValue)]), + ), + ); + } else { + const slotPropsSlotValue = property.value.properties.splice(slotIndex, 1)[0].value; + property.value.properties.push( + j.objectProperty( + j.identifier('listbox'), + j.objectExpression([ + j.objectProperty(j.identifier('component'), removedValue), + j.spreadElement(slotPropsSlotValue), + ]), + ), + ); + } + } + }); + + if (!hasSlotProps) { + defaultProps.properties.push( + j.objectProperty( + j.identifier('slotProps'), + j.objectExpression([ + j.objectProperty( + j.identifier('listbox'), + j.objectExpression([j.objectProperty(j.identifier('component'), removedValue)]), + ), + ]), + ), + ); + } + + path.prune(); + }); + 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 91256850d51b37..76a939df4f9629 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 @@ -2,6 +2,11 @@ import Autocomplete from '@mui/material/Autocomplete'; import {Autocomplete as MyAutocomplete} from '@mui/material'; ; ; ; + + 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 ca1cc8744cb73a..f18d47190402d5 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 @@ -2,16 +2,26 @@ import Autocomplete from '@mui/material/Autocomplete'; import {Autocomplete as MyAutocomplete} from '@mui/material'; ; + + listbox: { + component: CustomListbox, + ...{ height: 12 } + } + }} />; ; ; + + listbox: { + component: CustomListbox, + ...{ height: 12 } + } + }} />; ; + + 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 b2a362ab99a596..5b144b5440188b 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 @@ -1,6 +1,11 @@ fn({ MuiAutocomplete: { defaultProps: { + ChipProps: { height: 10 }, + PaperComponent: CustomPaper, + PopperComponent: CustomPopper, + ListboxComponent: CustomListbox, + ListboxProps: { height: 12 }, componentsProps: { clearIndicator: { width: 10 }, paper: { width: 12 }, @@ -14,6 +19,11 @@ fn({ fn({ MuiAutocomplete: { defaultProps: { + ChipProps: { height: 10 }, + PaperComponent: CustomPaper, + PopperComponent: CustomPopper, + ListboxComponent: CustomListbox, + ListboxProps: { height: 12 }, 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 06c6da749b8bf6..93e6dcda392428 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,11 +1,22 @@ fn({ MuiAutocomplete: { defaultProps: { + slots: { + paper: CustomPaper, + popper: CustomPopper + }, + slotProps: { clearIndicator: { width: 10 }, paper: { width: 12 }, popper: { width: 14 }, - popupIndicator: { width: 16 } + popupIndicator: { width: 16 }, + chip: { height: 10 }, + + listbox: { + component: CustomListbox, + ...{ height: 12 } + } } }, }, @@ -22,7 +33,19 @@ fn({ popupIndicator: { ...{ width: 16 }, ...{ width: 20 } + }, + + chip: { height: 10 }, + + listbox: { + component: CustomListbox, + ...{ height: 12 } } + }, + + slots: { + paper: CustomPaper, + popper: CustomPopper } }, }, diff --git a/packages/mui-codemod/src/deprecations/backdrop-props/backdrop-props.js b/packages/mui-codemod/src/deprecations/backdrop-props/backdrop-props.js index 1654904706db6b..0d831486177b84 100644 --- a/packages/mui-codemod/src/deprecations/backdrop-props/backdrop-props.js +++ b/packages/mui-codemod/src/deprecations/backdrop-props/backdrop-props.js @@ -1,3 +1,4 @@ +import movePropIntoSlots from '../utils/movePropIntoSlots'; import replaceComponentsWithSlots from '../utils/replaceComponentsWithSlots'; /** @@ -11,5 +12,12 @@ export default function transformer(file, api, options) { replaceComponentsWithSlots(j, { root, componentName: 'Backdrop' }); + movePropIntoSlots(j, { + root, + componentName: 'Backdrop', + propName: 'TransitionComponent', + slotName: 'transition', + }); + return root.toSource(printOptions); } diff --git a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/actual.js b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/actual.js index 3107ff6d22d408..f2df3ef6a74e10 100644 --- a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/actual.js +++ b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/actual.js @@ -1,6 +1,31 @@ import Backdrop from '@mui/material/Backdrop'; import { Backdrop as MyBackdrop } from '@mui/material'; +; +; +; +; +; + +// should skip non MUI components +; + ; ; ; diff --git a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/expected.js b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/expected.js index e1a26591a40b7f..a81133b9babe6d 100644 --- a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/expected.js +++ b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/expected.js @@ -1,6 +1,31 @@ import Backdrop from '@mui/material/Backdrop'; import { Backdrop as MyBackdrop } from '@mui/material'; +; +; +; +; +; + +// should skip non MUI components +; + ; diff --git a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.actual.js b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.actual.js index 47551ec725be36..bfb2da0b7c4393 100644 --- a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.actual.js +++ b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.actual.js @@ -1,3 +1,34 @@ +fn({ + MuiBackdrop: { + defaultProps: { + TransitionComponent: CustomTransition, + }, + }, +}); + +fn({ + MuiBackdrop: { + defaultProps: { + TransitionComponent: CustomTransition, + slots: { + root: 'div', + }, + }, + }, +}); + +fn({ + MuiBackdrop: { + defaultProps: { + TransitionComponent: ComponentTransition, + slots: { + root: 'div', + transition: SlotTransition + }, + }, + }, +}); + fn({ MuiBackdrop: { defaultProps: { diff --git a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.expected.js b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.expected.js index ddb91a2cde9ee6..fb75b1ec670c19 100644 --- a/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.expected.js +++ b/packages/mui-codemod/src/deprecations/backdrop-props/test-cases/theme.expected.js @@ -1,3 +1,35 @@ +fn({ + MuiBackdrop: { + defaultProps: { + slots: { + transition: CustomTransition + } + }, + }, +}); + +fn({ + MuiBackdrop: { + defaultProps: { + slots: { + root: 'div', + transition: CustomTransition + } + }, + }, +}); + +fn({ + MuiBackdrop: { + defaultProps: { + slots: { + root: 'div', + transition: SlotTransition + } + }, + }, +}); + fn({ MuiBackdrop: { defaultProps: { diff --git a/packages/mui-codemod/src/deprecations/step-label-props/step-label-props.js b/packages/mui-codemod/src/deprecations/step-label-props/step-label-props.js index d71fbba3a84810..b2fec09fa3b826 100644 --- a/packages/mui-codemod/src/deprecations/step-label-props/step-label-props.js +++ b/packages/mui-codemod/src/deprecations/step-label-props/step-label-props.js @@ -1,4 +1,6 @@ import replaceComponentsWithSlots from '../utils/replaceComponentsWithSlots'; +import movePropIntoSlots from '../utils/movePropIntoSlots'; +import movePropIntoSlotProps from '../utils/movePropIntoSlotProps'; /** * @param {import('jscodeshift').FileInfo} file @@ -11,5 +13,19 @@ export default function transformer(file, api, options) { replaceComponentsWithSlots(j, { root, componentName: 'StepLabel' }); + movePropIntoSlots(j, { + root, + componentName: 'StepLabel', + propName: 'StepIconComponent', + slotName: 'stepIcon', + }); + + movePropIntoSlotProps(j, { + root, + componentName: 'StepLabel', + propName: 'StepIconProps', + slotName: 'stepIcon', + }); + return root.toSource(printOptions); } diff --git a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/actual.js b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/actual.js index 9caf4e5a411080..20a1428f7b1598 100644 --- a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/actual.js +++ b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/actual.js @@ -6,3 +6,15 @@ import StepLabel from '@mui/material/StepLabel'; slotProps={{ label: slotLabelProps }} componentsProps={{ label: componentsLabelProps }} />; +; +; +; diff --git a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/expected.js b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/expected.js index b26c217086b36d..3dfec474599baf 100644 --- a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/expected.js +++ b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/expected.js @@ -7,3 +7,29 @@ import StepLabel from '@mui/material/StepLabel'; ...componentsLabelProps, ...slotLabelProps } }} />; +; +; +; diff --git a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.actual.js b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.actual.js index 4f68c1fe687871..68624f70881f49 100644 --- a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.actual.js +++ b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.actual.js @@ -14,3 +14,23 @@ fn({ }, }, }); + +fn({ + MuiStepLabel: { + defaultProps: { + StepIconComponent: StepIconComponent, + StepIconProps: StepIconProps, + }, + }, +}); + +fn({ + MuiStepLabel: { + defaultProps: { + componentsProps: { label: componentsLabelProps }, + slotProps: { label: slotLabelProps }, + StepIconComponent: StepIconComponent, + StepIconProps: StepIconProps, + }, + }, +}); diff --git a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.expected.js b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.expected.js index c8874c72137cab..3919652d47b97d 100644 --- a/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.expected.js +++ b/packages/mui-codemod/src/deprecations/step-label-props/test-cases/theme.expected.js @@ -20,3 +20,36 @@ fn({ }, }, }); + +fn({ + MuiStepLabel: { + defaultProps: { + slots: { + stepIcon: StepIconComponent + }, + + slotProps: { + stepIcon: StepIconProps + } + }, + }, +}); + +fn({ + MuiStepLabel: { + defaultProps: { + slotProps: { + label: { + ...componentsLabelProps, + ...slotLabelProps + }, + + stepIcon: StepIconProps + }, + + slots: { + stepIcon: StepIconComponent + } + }, + }, +}); diff --git a/packages/mui-material/src/Accordion/Accordion.d.ts b/packages/mui-material/src/Accordion/Accordion.d.ts index 0956a67a00f033..283032d6133d64 100644 --- a/packages/mui-material/src/Accordion/Accordion.d.ts +++ b/packages/mui-material/src/Accordion/Accordion.d.ts @@ -90,6 +90,7 @@ export type AccordionTypeMap< /** * The component used for the transition. * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. + * @deprecated Use `slots.transition` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ TransitionComponent?: React.JSXElementConstructor< TransitionProps & { children?: React.ReactElement } @@ -97,6 +98,7 @@ export type AccordionTypeMap< /** * Props applied to the transition element. * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component. + * @deprecated Use `slotProps.transition` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ TransitionProps?: TransitionProps; } & AccordionSlotsAndSlotProps; diff --git a/packages/mui-material/src/Accordion/Accordion.js b/packages/mui-material/src/Accordion/Accordion.js index fd74ca6f342d29..2b37deea04ee27 100644 --- a/packages/mui-material/src/Accordion/Accordion.js +++ b/packages/mui-material/src/Accordion/Accordion.js @@ -322,11 +322,13 @@ Accordion.propTypes /* remove-proptypes */ = { /** * The component used for the transition. * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. + * @deprecated Use `slots.transition` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ TransitionComponent: PropTypes.elementType, /** * Props applied to the transition element. * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component. + * @deprecated Use `slotProps.transition` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ TransitionProps: PropTypes.object, }; diff --git a/packages/mui-material/src/Autocomplete/Autocomplete.d.ts b/packages/mui-material/src/Autocomplete/Autocomplete.d.ts index 91028debe19ad3..48eac3e2ba5d5f 100644 --- a/packages/mui-material/src/Autocomplete/Autocomplete.d.ts +++ b/packages/mui-material/src/Autocomplete/Autocomplete.d.ts @@ -167,6 +167,7 @@ export interface AutocompleteProps< AutocompleteSlotsAndSlotProps { /** * Props applied to the [`Chip`](https://mui.com/material-ui/api/chip/) element. + * @deprecated Use `slotProps.chip` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ ChipProps?: ChipProps; /** @@ -233,10 +234,12 @@ export interface AutocompleteProps< /** * The component used to render the listbox. * @default 'ul' + * @deprecated Use `slotProps.listbox.component` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ ListboxComponent?: React.JSXElementConstructor>; /** * Props applied to the Listbox element. + * @deprecated Use `slotProps.listbox` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ ListboxProps?: ReturnType['getListboxProps']> & { sx?: SxProps; @@ -281,11 +284,13 @@ export interface AutocompleteProps< /** * The component used to render the body of the popup. * @default Paper + * @deprecated Use `slots.paper` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ PaperComponent?: React.JSXElementConstructor>; /** * The component used to position the popup. * @default Popper + * @deprecated Use `slots.popper` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ PopperComponent?: React.JSXElementConstructor; /** diff --git a/packages/mui-material/src/Autocomplete/Autocomplete.js b/packages/mui-material/src/Autocomplete/Autocomplete.js index ff70335f6f0986..555ec43bb213c1 100644 --- a/packages/mui-material/src/Autocomplete/Autocomplete.js +++ b/packages/mui-material/src/Autocomplete/Autocomplete.js @@ -828,6 +828,7 @@ Autocomplete.propTypes /* remove-proptypes */ = { blurOnSelect: PropTypes.oneOfType([PropTypes.oneOf(['mouse', 'touch']), PropTypes.bool]), /** * Props applied to the [`Chip`](https://mui.com/material-ui/api/chip/) element. + * @deprecated Use `slotProps.chip` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ ChipProps: PropTypes.object, /** @@ -1035,10 +1036,12 @@ Autocomplete.propTypes /* remove-proptypes */ = { /** * The component used to render the listbox. * @default 'ul' + * @deprecated Use `slotProps.listbox.component` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ ListboxComponent: PropTypes.elementType, /** * Props applied to the Listbox element. + * @deprecated Use `slotProps.listbox` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ ListboxProps: PropTypes.object, /** @@ -1133,11 +1136,13 @@ Autocomplete.propTypes /* remove-proptypes */ = { /** * The component used to render the body of the popup. * @default Paper + * @deprecated Use `slots.paper` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ PaperComponent: PropTypes.elementType, /** * The component used to position the popup. * @default Popper + * @deprecated Use `slots.popper` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ PopperComponent: PropTypes.elementType, /** diff --git a/packages/mui-material/src/Avatar/Avatar.d.ts b/packages/mui-material/src/Avatar/Avatar.d.ts index 804b4c6c7656db..ba60904d7c5b60 100644 --- a/packages/mui-material/src/Avatar/Avatar.d.ts +++ b/packages/mui-material/src/Avatar/Avatar.d.ts @@ -46,6 +46,7 @@ export interface AvatarOwnProps { /** * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attributes) applied to the `img` element if the component is used to display an image. * It can be used to listen for the loading error event. + * @deprecated Use `slotProps.img` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ imgProps?: React.ImgHTMLAttributes & { sx?: SxProps; diff --git a/packages/mui-material/src/Avatar/Avatar.js b/packages/mui-material/src/Avatar/Avatar.js index 0ba9e1cf8ee8e2..50157ee01ef149 100644 --- a/packages/mui-material/src/Avatar/Avatar.js +++ b/packages/mui-material/src/Avatar/Avatar.js @@ -246,6 +246,7 @@ Avatar.propTypes /* remove-proptypes */ = { /** * [Attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img#attributes) applied to the `img` element if the component is used to display an image. * It can be used to listen for the loading error event. + * @deprecated Use `slotProps.img` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ imgProps: PropTypes.object, /** diff --git a/packages/mui-material/src/Backdrop/Backdrop.d.ts b/packages/mui-material/src/Backdrop/Backdrop.d.ts index 54c522613c0a47..e4ef50ac1de928 100644 --- a/packages/mui-material/src/Backdrop/Backdrop.d.ts +++ b/packages/mui-material/src/Backdrop/Backdrop.d.ts @@ -97,6 +97,7 @@ export interface BackdropOwnProps * The component used for the transition. * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. * @default Fade + * @deprecated Use `slots.transition` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ TransitionComponent?: React.JSXElementConstructor< TransitionProps & { diff --git a/packages/mui-material/src/Backdrop/Backdrop.js b/packages/mui-material/src/Backdrop/Backdrop.js index 1c906c65260986..7e4f6e1a5b6591 100644 --- a/packages/mui-material/src/Backdrop/Backdrop.js +++ b/packages/mui-material/src/Backdrop/Backdrop.js @@ -193,6 +193,7 @@ Backdrop.propTypes /* remove-proptypes */ = { * The component used for the transition. * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. * @default Fade + * @deprecated Use `slots.transition` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ TransitionComponent: PropTypes.elementType, /** diff --git a/packages/mui-material/src/SpeedDial/SpeedDial.d.ts b/packages/mui-material/src/SpeedDial/SpeedDial.d.ts index c3076ce770175f..d255e40019d9b4 100644 --- a/packages/mui-material/src/SpeedDial/SpeedDial.d.ts +++ b/packages/mui-material/src/SpeedDial/SpeedDial.d.ts @@ -97,6 +97,7 @@ export interface SpeedDialProps * The component used for the transition. * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. * @default Zoom + * * @deprecated Use `slots.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) */ TransitionComponent?: React.JSXElementConstructor; /** @@ -111,6 +112,7 @@ export interface SpeedDialProps /** * Props applied to the transition element. * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component. + * @deprecated Use `slotProps.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) */ TransitionProps?: TransitionProps; } diff --git a/packages/mui-material/src/SpeedDial/SpeedDial.js b/packages/mui-material/src/SpeedDial/SpeedDial.js index 8d9d9fdbe4197e..96c97c6b58cad2 100644 --- a/packages/mui-material/src/SpeedDial/SpeedDial.js +++ b/packages/mui-material/src/SpeedDial/SpeedDial.js @@ -555,6 +555,7 @@ SpeedDial.propTypes /* remove-proptypes */ = { * The component used for the transition. * [Follow this guide](https://mui.com/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component. * @default Zoom + * * @deprecated Use `slots.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) */ TransitionComponent: PropTypes.elementType, /** @@ -576,6 +577,7 @@ SpeedDial.propTypes /* remove-proptypes */ = { /** * Props applied to the transition element. * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component. + * @deprecated Use `slotProps.transition` instead. This prop will be removed in v7. [How to migrate](/material-ui/migration/migrating-from-deprecated-apis/) */ TransitionProps: PropTypes.object, }; diff --git a/packages/mui-material/src/StepLabel/StepLabel.d.ts b/packages/mui-material/src/StepLabel/StepLabel.d.ts index 7e4d8850401508..4139cc91998ad9 100644 --- a/packages/mui-material/src/StepLabel/StepLabel.d.ts +++ b/packages/mui-material/src/StepLabel/StepLabel.d.ts @@ -66,10 +66,12 @@ export interface StepLabelProps optional?: React.ReactNode; /** * The component to render in place of the [`StepIcon`](https://mui.com/material-ui/api/step-icon/). + * @deprecated Use `slots.stepIcon` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ StepIconComponent?: React.ElementType; /** * Props applied to the [`StepIcon`](https://mui.com/material-ui/api/step-icon/) element. + * @deprecated Use `slotProps.stepIcon` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ StepIconProps?: Partial; /** diff --git a/packages/mui-material/src/StepLabel/StepLabel.js b/packages/mui-material/src/StepLabel/StepLabel.js index fc590de90098a2..4567f3bac0fbd6 100644 --- a/packages/mui-material/src/StepLabel/StepLabel.js +++ b/packages/mui-material/src/StepLabel/StepLabel.js @@ -273,10 +273,12 @@ StepLabel.propTypes /* remove-proptypes */ = { }), /** * The component to render in place of the [`StepIcon`](https://mui.com/material-ui/api/step-icon/). + * @deprecated Use `slots.stepIcon` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ StepIconComponent: PropTypes.elementType, /** * Props applied to the [`StepIcon`](https://mui.com/material-ui/api/step-icon/) element. + * @deprecated Use `slotProps.stepIcon` instead. This prop will be removed in v7. See [Migrating from deprecated APIs](/material-ui/migration/migrating-from-deprecated-apis/) for more details. */ StepIconProps: PropTypes.object, /** From 902b73b5503a54d6afd00d91b509ba60f1ff94c4 Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sun, 17 Nov 2024 20:03:54 +0100 Subject: [PATCH 13/14] [docs] Add App starters in related-projects.md (#44315) Signed-off-by: Olivier Tassinari Co-authored-by: Sycamore <71297412+samuelsycamore@users.noreply.github.com> --- .../material/components/dialogs/dialogs.md | 2 +- docs/data/material/components/menus/menus.md | 2 +- .../material/components/popover/popover.md | 2 +- .../data/material/components/popper/popper.md | 2 +- .../components/snackbars/snackbars.md | 2 +- .../components/text-fields/text-fields.md | 8 +-- .../related-projects/related-projects.md | 64 +++++++++++-------- 7 files changed, 47 insertions(+), 35 deletions(-) diff --git a/docs/data/material/components/dialogs/dialogs.md b/docs/data/material/components/dialogs/dialogs.md index c12c0b7a4306ec..47e02ab2dbb4bb 100644 --- a/docs/data/material/components/dialogs/dialogs.md +++ b/docs/data/material/components/dialogs/dialogs.md @@ -153,7 +153,7 @@ Follow the [Modal performance section](/material-ui/react-modal/#performance). Follow the [Modal limitations section](/material-ui/react-modal/#limitations). -## Complementary projects +## Supplementary projects For more advanced use cases you might be able to take advantage of: diff --git a/docs/data/material/components/menus/menus.md b/docs/data/material/components/menus/menus.md index ca8b591883b6de..f8b357ae77bdcc 100644 --- a/docs/data/material/components/menus/menus.md +++ b/docs/data/material/components/menus/menus.md @@ -107,7 +107,7 @@ Here is an example of a context menu. (Right click to open.) {{"demo": "ContextMenu.js"}} -## Complementary projects +## Supplementary projects For more advanced use cases you might be able to take advantage of: diff --git a/docs/data/material/components/popover/popover.md b/docs/data/material/components/popover/popover.md index 9aceeb3c6dd248..ec1c1fd1ab8d53 100644 --- a/docs/data/material/components/popover/popover.md +++ b/docs/data/material/components/popover/popover.md @@ -64,7 +64,7 @@ The usage of a virtual element for the Popover component requires the `nodeType` This is different from virtual elements used for the [`Popper`](/material-ui/react-popper/#virtual-element) or [`Tooltip`](/material-ui/react-tooltip/#virtual-element) components, both of which don't require the property. ::: -## Complementary projects +## Supplementary projects For more advanced use cases, you might be able to take advantage of: diff --git a/docs/data/material/components/popper/popper.md b/docs/data/material/components/popper/popper.md index d88359dd7b90f0..f7101d8df762ba 100644 --- a/docs/data/material/components/popper/popper.md +++ b/docs/data/material/components/popper/popper.md @@ -64,7 +64,7 @@ Highlight part of the text to see the popper: {{"demo": "VirtualElementPopper.js"}} -## Complementary projects +## Supplementary projects For more advanced use cases you might be able to take advantage of: diff --git a/docs/data/material/components/snackbars/snackbars.md b/docs/data/material/components/snackbars/snackbars.md index 7b50dc4fc504eb..8a683a5e617aee 100644 --- a/docs/data/material/components/snackbars/snackbars.md +++ b/docs/data/material/components/snackbars/snackbars.md @@ -87,7 +87,7 @@ This demo shows how to display multiple Snackbars without stacking them by using {{"demo": "ConsecutiveSnackbars.js"}} -## Third-party integrations +## Supplementary components ### notistack diff --git a/docs/data/material/components/text-fields/text-fields.md b/docs/data/material/components/text-fields/text-fields.md index 583fe3cd894ef5..8fc5d00dc42fa1 100644 --- a/docs/data/material/components/text-fields/text-fields.md +++ b/docs/data/material/components/text-fields/text-fields.md @@ -353,13 +353,13 @@ In order for the text field to be accessible, **the input should be linked to th ``` -## Complementary projects +## Supplementary projects + + For more advanced use cases, you might be able to take advantage of: -- [react-hook-form](https://react-hook-form.com/): React hook for form validation. -- [react-hook-form-mui](https://github.com/dohomi/react-hook-form-mui): Material UI and react-hook-form combined. +- [react-hook-form-mui](https://github.com/dohomi/react-hook-form-mui): Material UI and [react-hook-form](https://react-hook-form.com/) combined. - [formik-material-ui](https://github.com/stackworx/formik-mui): Bindings for using Material UI with [formik](https://formik.org/). - [mui-rff](https://github.com/lookfirst/mui-rff): Bindings for using Material UI with [React Final Form](https://final-form.org/react). - [@ui-schema/ds-material](https://www.npmjs.com/package/@ui-schema/ds-material) Bindings for using Material UI with [UI Schema](https://github.com/ui-schema/ui-schema). JSON Schema compatible. -- [@data-driven-forms/mui-component-mapper](https://www.data-driven-forms.org/provided-mappers/mui-component-mapper): Bindings for using Material UI with [Data Driven Forms](https://github.com/data-driven-forms/react-forms). diff --git a/docs/data/material/discover-more/related-projects/related-projects.md b/docs/data/material/discover-more/related-projects/related-projects.md index 93f895c38b3fff..32d09fc0f80dbb 100644 --- a/docs/data/material/discover-more/related-projects/related-projects.md +++ b/docs/data/material/discover-more/related-projects/related-projects.md @@ -1,69 +1,81 @@ # Related projects -

A carefully curated list of third-party tools that expand or build on top of Material UI.

+

A carefully curated list of tools that expand or build on top of Material UI.

-Developers from the community have built some excellent supplemental tools for working with Material UI—this page highlights some of the best that we've seen. +The MUI org and developers from the community have built some excellent supplemental tools for working with Material UI—this page highlights some of the best that we've seen. Do you have a project that you think should be featured here? Feel free to submit a pull request and the maintainers will work with you to write the description. -## Premium tools +## Third-party app starters -- [ScaffoldHub](https://v2.scaffoldhub.io/scaffolds/react-material-ui?partner=1): +### Admin frameworks - - Tool for building web applications. - - Choose your framework and library (React with Material UI). - - Choose your database (SQL, MongoDB or Firestore). - - Model your database and application with the intuitive GUI. - - Generate your application, including a complete scaffolded backend. - - Preview your application online and download the generated code. +- [React-admin](https://github.com/marmelab/react-admin): A front-end framework for building data-driven applications running in the browser on top of REST/GraphQL APIs. +- [Refine](https://github.com/refinedev/refine): An open source, headless React meta-framework for the rapid development of web applications. + +### Paid starters - [Divjoy](https://divjoy.com?via=material-ui): - Create a Material UI app in minutes. - Templates, authentication, database integration, subscription payments, and more. -## Free tools - -### Admin frameworks - -- [React-admin](https://github.com/marmelab/react-admin): A front-end framework for building data-driven applications running in the browser on top of REST/GraphQL APIs. -- [Refine](https://github.com/refinedev/refine): An open source, headless React meta-framework for the rapid development of web applications. +- [ScaffoldHub](https://v2.scaffoldhub.io/scaffolds/react-material-ui?partner=1): + - Tool for building web applications. + - Choose your framework and library (React with Material UI). + - Choose your database (SQL, MongoDB or Firestore). + - Model your database and application with the intuitive GUI. + - Generate your application, including a complete scaffolded backend. + - Preview your application online and download the generated code. -### Theming tools +## Third-party theming tools - [Material palette generator](https://m2.material.io/inline-tools/color/): The official Material Design 2 palette generator tool. -### Supplementary components +## Supplementary components -#### Layout +### Layout - [MUI Treasury Layout](https://mui-treasury.com/?path=/docs/layout-v6-introduction--docs): Components to handle the overall layout of a page. Check out examples such as [a legacy.reactjs.org clone](https://mui-treasury.com/?path=/story/layout-v6-app-react-legacy--react-legacy). -#### Image +### Image - [mui-image](https://github.com/benmneb/mui-image): The only Material UI image component to satisfy the Material Design 2 guidelines for loading images. -#### Chips input +### Chips input - [mui-chips-input](https://github.com/viclafouch/mui-chips-input): A chips input designed for use with Material UI. -#### Phone number input +### Phone number input - [mui-tel-input](https://github.com/viclafouch/mui-tel-input): A phone number input designed for use with Material UI, built with [libphonenumber-js](https://www.npmjs.com/package/libphonenumber-js). -#### One-time password input +### One-time password input - [mui-otp-input](https://github.com/viclafouch/mui-otp-input): A one-time password input designed for use with Material UI. -#### File input +### File input - [mui-file-input](https://github.com/viclafouch/mui-file-input): A file input designed for use with Material UI. -#### Color input +### Color input - [mui-color-input](https://github.com/viclafouch/mui-color-input): A color input designed for use with Material UI, built with [TinyColor](https://tinycolor.vercel.app/). -#### Rich text editor +### Rich text editor - [mui-tiptap](https://github.com/sjdemartini/mui-tiptap): A customizable Material UI-styled WYSIWYG rich text editor, built with [Tiptap](https://tiptap.dev/). + +### Form + + + +- [react-hook-form-mui](https://github.com/dohomi/react-hook-form-mui): Material UI and [react-hook-form](https://react-hook-form.com/) combined. +- [formik-material-ui](https://github.com/stackworx/formik-mui): Bindings for using Material UI with [formik](https://formik.org/). +- [mui-rff](https://github.com/lookfirst/mui-rff): Bindings for using Material UI with [React Final Form](https://final-form.org/react). +- [@ui-schema/ds-material](https://www.npmjs.com/package/@ui-schema/ds-material) Bindings for using Material UI with [UI Schema](https://github.com/ui-schema/ui-schema). JSON Schema compatible. + +### Notification + +- [notistack](https://github.com/iamhosseindhv/notistack): Display multiple snackbars that can be stacked and queued—this tool makes it simpler to handle the open and close states. From aef2bf2234f95b5e2614c2645f0fec5c355a248b Mon Sep 17 00:00:00 2001 From: Olivier Tassinari Date: Sun, 17 Nov 2024 23:08:24 +0100 Subject: [PATCH 14/14] [core] Keep OpenSSF badge up-to-date --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8b4962c352edc4..b9a9531f02b98f 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ [![Renovate status](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://github.com/mui/material-ui/issues/27062) [![Average time to resolve an issue](https://isitmaintained.com/badge/resolution/mui/material-ui.svg)](https://isitmaintained.com/project/mui/material-ui 'Average time to resolve an issue') [![Open Collective backers and sponsors](https://img.shields.io/opencollective/all/mui-org)](https://opencollective.com/mui-org) -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1320/badge)](https://bestpractices.coreinfrastructure.org/projects/1320) +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/1320/badge)](https://www.bestpractices.dev/projects/1320)