diff --git a/docs/pages/material-ui/api/loading-button.json b/docs/pages/material-ui/api/loading-button.json index 555074c1ad71b8..8155927a65f266 100644 --- a/docs/pages/material-ui/api/loading-button.json +++ b/docs/pages/material-ui/api/loading-button.json @@ -217,6 +217,12 @@ "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", diff --git a/docs/translations/api-docs/loading-button/loading-button.json b/docs/translations/api-docs/loading-button/loading-button.json index 893accc5f50691..9babb1623d14c9 100644 --- a/docs/translations/api-docs/loading-button/loading-button.json +++ b/docs/translations/api-docs/loading-button/loading-button.json @@ -168,6 +168,10 @@ "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", diff --git a/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts b/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts index 6dc2341f9f5265..90351bc0f2a15c 100644 --- a/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts +++ b/packages/mui-lab/src/LoadingButton/LoadingButton.d.ts @@ -10,6 +10,8 @@ export interface LoadingButtonOwnProps { 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. */ diff --git a/packages/mui-lab/src/LoadingButton/LoadingButton.js b/packages/mui-lab/src/LoadingButton/LoadingButton.js index 13d5a9aec21df1..12f0997a888d09 100644 --- a/packages/mui-lab/src/LoadingButton/LoadingButton.js +++ b/packages/mui-lab/src/LoadingButton/LoadingButton.js @@ -2,7 +2,11 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import { chainPropTypes } from '@mui/utils'; -import { capitalize, unstable_useId as useId } from '@mui/material/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'; @@ -17,6 +21,7 @@ const useUtilityClasses = (ownerState) => { const slots = { root: ['root', loading && 'loading'], + label: ['label'], startIcon: [loading && `startIconLoading${capitalize(loadingPosition)}`], endIcon: [loading && `endIconLoading${capitalize(loadingPosition)}`], loadingIndicator: [ @@ -51,56 +56,59 @@ const LoadingButtonRoot = styled(Button, { }, ]; }, -})(({ theme }) => ({ - [`& .${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'], { +})( + memoTheme(({ theme }) => ({ + display: 'inline-flex', + [`& .${loadingButtonClasses.startIconLoadingStart}, & .${loadingButtonClasses.endIconLoadingEnd}`]: + { + transition: theme.transitions.create(['opacity'], { duration: theme.transitions.duration.short, }), - [`&.${loadingButtonClasses.loading}`]: { - color: 'transparent', - }, + opacity: 0, }, - }, - { - 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, + 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 === 'end' && ownerState.fullWidth, - style: { - [`& .${loadingButtonClasses.startIconLoadingStart}, & .${loadingButtonClasses.endIconLoadingEnd}`]: - { - transition: theme.transitions.create(['opacity'], { - duration: theme.transitions.duration.short, - }), - opacity: 0, - marginLeft: -8, - }, + { + 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', @@ -112,87 +120,101 @@ const LoadingButtonLoadingIndicator = styled('span', { styles[`loadingIndicator${capitalize(ownerState.loadingPosition)}`], ]; }, -})(({ 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', +})( + memoTheme(({ theme }) => ({ + position: 'absolute', + visibility: 'visible', + display: 'flex', + variants: [ + { + props: { + loadingPosition: 'start', + size: 'small', + }, + style: { + left: 10, + }, }, - style: { - left: '50%', - transform: 'translate(-50%)', - color: (theme.vars || theme).palette.action.disabled, + { + props: ({ loadingPosition, ownerState }) => + loadingPosition === 'start' && ownerState.size !== 'small', + style: { + left: 14, + }, }, - }, - { - props: { - loadingPosition: 'end', - size: 'small', + { + props: { + variant: 'text', + loadingPosition: 'start', + }, + style: { + left: 6, + }, }, - style: { - right: 10, + { + props: { + loadingPosition: 'center', + }, + style: { + left: '50%', + transform: 'translate(-50%)', + color: (theme.vars || theme).palette.action.disabled, + }, }, - }, - { - props: ({ loadingPosition, ownerState }) => - loadingPosition === 'end' && ownerState.size !== 'small', - style: { - right: 14, + { + props: { + loadingPosition: 'end', + size: 'small', + }, + style: { + right: 10, + }, }, - }, - { - props: { - variant: 'text', - loadingPosition: 'end', + { + props: ({ loadingPosition, ownerState }) => + loadingPosition === 'end' && ownerState.size !== 'small', + style: { + right: 14, + }, }, - style: { - right: 6, + { + props: { + variant: 'text', + loadingPosition: 'end', + }, + style: { + right: 6, + }, }, - }, - { - props: ({ ownerState }) => ownerState.loadingPosition === 'start' && ownerState.fullWidth, - style: { - position: 'relative', - left: -10, + { + props: ({ ownerState }) => ownerState.loadingPosition === 'start' && ownerState.fullWidth, + style: { + position: 'relative', + left: -10, + }, }, - }, - { - props: ({ ownerState }) => ownerState.loadingPosition === 'end' && ownerState.fullWidth, - style: { - position: 'relative', - right: -10, + { + props: ({ ownerState }) => ownerState.loadingPosition === 'end' && ownerState.fullWidth, + style: { + position: 'relative', + right: -10, + }, }, - }, - ], -})); + ], + })), +); + +const LoadingButtonLabel = styled('span', { + name: 'MuiLoadingButton', + slot: 'Label', + overridesResolver: (props, styles) => { + return [styles.label]; + }, +})({ + display: 'inherit', + alignItems: 'inherit', + justifyContent: 'inherit', +}); const LoadingButton = React.forwardRef(function LoadingButton(inProps, ref) { const contextProps = React.useContext(ButtonGroupContext); @@ -242,7 +264,7 @@ const LoadingButton = React.forwardRef(function LoadingButton(inProps, ref) { ownerState={ownerState} > {ownerState.loadingPosition === 'end' ? ( - {children} + {children} ) : ( loadingButtonLoadingIndicator )} @@ -250,7 +272,7 @@ const LoadingButton = React.forwardRef(function LoadingButton(inProps, ref) { {ownerState.loadingPosition === 'end' ? ( loadingButtonLoadingIndicator ) : ( - {children} + {children} )} ); diff --git a/packages/mui-lab/src/LoadingButton/loadingButtonClasses.ts b/packages/mui-lab/src/LoadingButton/loadingButtonClasses.ts index d4adaf87799f78..d6543a1fa86cab 100644 --- a/packages/mui-lab/src/LoadingButton/loadingButtonClasses.ts +++ b/packages/mui-lab/src/LoadingButton/loadingButtonClasses.ts @@ -4,6 +4,8 @@ import generateUtilityClasses from '@mui/utils/generateUtilityClasses'; export interface LoadingButtonClasses { /** 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. */ @@ -28,6 +30,7 @@ export function getLoadingButtonUtilityClass(slot: string): string { const loadingButtonClasses: LoadingButtonClasses = generateUtilityClasses('MuiLoadingButton', [ 'root', + 'label', 'loading', 'loadingIndicator', 'loadingIndicatorCenter', diff --git a/packages/mui-material/src/utils/index.d.ts b/packages/mui-material/src/utils/index.d.ts index 7ccd7522ee6ff5..ccba6bbec929e1 100644 --- a/packages/mui-material/src/utils/index.d.ts +++ b/packages/mui-material/src/utils/index.d.ts @@ -5,6 +5,7 @@ export { default as createSvgIcon } from './createSvgIcon'; export { default as debounce } from './debounce'; export { default as deprecatedPropType } from './deprecatedPropType'; export { default as isMuiElement } from './isMuiElement'; +export { default as unstable_memoTheme } from './memoTheme'; export { default as ownerDocument } from './ownerDocument'; export { default as ownerWindow } from './ownerWindow'; export { default as requirePropFactory } from './requirePropFactory'; diff --git a/packages/mui-material/src/utils/index.js b/packages/mui-material/src/utils/index.js index 90b88322517ab1..a43e01cd154380 100644 --- a/packages/mui-material/src/utils/index.js +++ b/packages/mui-material/src/utils/index.js @@ -7,6 +7,7 @@ export { default as createSvgIcon } from './createSvgIcon'; export { default as debounce } from './debounce'; export { default as deprecatedPropType } from './deprecatedPropType'; export { default as isMuiElement } from './isMuiElement'; +export { default as unstable_memoTheme } from './memoTheme'; export { default as ownerDocument } from './ownerDocument'; export { default as ownerWindow } from './ownerWindow'; export { default as requirePropFactory } from './requirePropFactory';