Skip to content

Commit 33ce030

Browse files
authored
[material-ui][IconButton] Set default loading to null (#45057)
1 parent a32b12a commit 33ce030

File tree

6 files changed

+38
-9
lines changed

6 files changed

+38
-9
lines changed

docs/pages/material-ui/api/icon-button.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
},
2020
"default": "false"
2121
},
22-
"loading": { "type": { "name": "bool" }, "default": "false" },
22+
"loading": { "type": { "name": "bool" }, "default": "null" },
2323
"loadingIndicator": {
2424
"type": { "name": "node" },
2525
"default": "<CircularProgress color=\"inherit\" size={16} />"
@@ -117,6 +117,12 @@
117117
"description": "Styles applied to the loadingIndicator element.",
118118
"isGlobal": false
119119
},
120+
{
121+
"key": "loadingWrapper",
122+
"className": "MuiIconButton-loadingWrapper",
123+
"description": "Styles applied to the loadingWrapper element.",
124+
"isGlobal": false
125+
},
120126
{
121127
"key": "root",
122128
"className": "MuiIconButton-root",

docs/translations/api-docs/icon-button/icon-button.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"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)."
1818
},
1919
"loading": {
20-
"description": "If <code>true</code>, the loading indicator is visible and the button is disabled."
20+
"description": "If <code>true</code>, the loading indicator is visible and the button is disabled. If <code>true \\| false</code>, the loading wrapper is always rendered before the children to prevent <a href=\"https://github.com/mui/material-ui/issues/27853\">Google Translation Crash</a>."
2121
},
2222
"loadingIndicator": {
2323
"description": "Element placed before the children if the button is in loading state. The node should contain an element with <code>role=&quot;progressbar&quot;</code> with an accessible name. By default, it renders a <code>CircularProgress</code> that is labeled by the button itself."
@@ -89,6 +89,10 @@
8989
"description": "Styles applied to {{nodeName}}.",
9090
"nodeName": "the loadingIndicator element"
9191
},
92+
"loadingWrapper": {
93+
"description": "Styles applied to {{nodeName}}.",
94+
"nodeName": "the loadingWrapper element"
95+
},
9296
"root": { "description": "Styles applied to the root element." },
9397
"sizeLarge": {
9498
"description": "Styles applied to {{nodeName}} if {{conditions}}.",

packages/mui-material/src/IconButton/IconButton.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ export interface IconButtonOwnProps {
4949
edge?: 'start' | 'end' | false;
5050
/**
5151
* If `true`, the loading indicator is visible and the button is disabled.
52-
* @default false
52+
* If `true | false`, the loading wrapper is always rendered before the children to prevent [Google Translation Crash](https://github.com/mui/material-ui/issues/27853).
53+
* @default null
5354
*/
54-
loading?: boolean;
55+
loading?: boolean | null;
5556
/**
5657
* Element placed before the children if the button is in loading state.
5758
* The node should contain an element with `role="progressbar"` with an accessible name.

packages/mui-material/src/IconButton/IconButton.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const useUtilityClasses = (ownerState) => {
2828
`size${capitalize(size)}`,
2929
],
3030
loadingIndicator: ['loadingIndicator'],
31+
loadingWrapper: ['loadingWrapper'],
3132
};
3233

3334
return composeClasses(slots, getIconButtonUtilityClass, classes);
@@ -181,7 +182,7 @@ const IconButton = React.forwardRef(function IconButton(inProps, ref) {
181182
disableFocusRipple = false,
182183
size = 'medium',
183184
id: idProp,
184-
loading = false,
185+
loading = null,
185186
loadingIndicator: loadingIndicatorProp,
186187
...other
187188
} = props;
@@ -215,9 +216,14 @@ const IconButton = React.forwardRef(function IconButton(inProps, ref) {
215216
{...other}
216217
ownerState={ownerState}
217218
>
218-
<IconButtonLoadingIndicator className={classes.loadingIndicator} ownerState={ownerState}>
219-
{loading && loadingIndicator}
220-
</IconButtonLoadingIndicator>
219+
{typeof loading === 'boolean' && (
220+
// use plain HTML span to minimize the runtime overhead
221+
<span className={classes.loadingWrapper} style={{ display: 'contents' }}>
222+
<IconButtonLoadingIndicator className={classes.loadingIndicator} ownerState={ownerState}>
223+
{loading && loadingIndicator}
224+
</IconButtonLoadingIndicator>
225+
</span>
226+
)}
221227
{children}
222228
</IconButtonRoot>
223229
);
@@ -307,7 +313,8 @@ IconButton.propTypes /* remove-proptypes */ = {
307313
id: PropTypes.string,
308314
/**
309315
* If `true`, the loading indicator is visible and the button is disabled.
310-
* @default false
316+
* If `true | false`, the loading wrapper is always rendered before the children to prevent [Google Translation Crash](https://github.com/mui/material-ui/issues/27853).
317+
* @default null
311318
*/
312319
loading: PropTypes.bool,
313320
/**

packages/mui-material/src/IconButton/IconButton.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ describe('<IconButton />', () => {
163163
});
164164

165165
describe('prop: loading', () => {
166+
it('does not render the wrapper by default', () => {
167+
render(<IconButton />);
168+
169+
const button = screen.getByRole('button');
170+
expect(button).to.have.property('disabled', false);
171+
expect(button.firstChild).to.equal(null);
172+
});
173+
166174
it('disables the button', () => {
167175
render(<IconButton loading />);
168176

packages/mui-material/src/IconButton/iconButtonClasses.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ export interface IconButtonClasses {
3434
loading: string;
3535
/** Styles applied to the loadingIndicator element. */
3636
loadingIndicator: string;
37+
/** Styles applied to the loadingWrapper element. */
38+
loadingWrapper: string;
3739
}
3840

3941
export type IconButtonClassKey = keyof IconButtonClasses;
@@ -59,6 +61,7 @@ const iconButtonClasses: IconButtonClasses = generateUtilityClasses('MuiIconButt
5961
'sizeLarge',
6062
'loading',
6163
'loadingIndicator',
64+
'loadingWrapper',
6265
]);
6366

6467
export default iconButtonClasses;

0 commit comments

Comments
 (0)