Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Button] Add loading prop #44637

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

siriwatknp
Copy link
Member

@siriwatknp siriwatknp commented Dec 3, 2024

Preview: https://deploy-preview-44637--material-ui.netlify.app/material-ui/react-button/#loading-2

Closes #42684
Closes #31235

Context

This PR build on top of the reverted #42987 by making the default value of loading to be null to fix the problem with Google Translation Crash without introducing overhead of the loading wrapper to the existing projects.

When the prop is boolean, a span always present as a wrapper regardless of the loading state:

<button>
  <span style={{ display: 'contents' }}></span> // still present even though loading is false
  text
</button>

The reasons to go with this approach instead of wrapping children with a span are:

  • No breaking change
  • No overhead for existing projects
  • Small overhead when loading because the loading wrapper is not build with styled.

Note

When this PR is merged, the next release should be v6.2.0


@siriwatknp siriwatknp added new feature New feature or request component: button This is the name of the generic UI component, not the React module! labels Dec 3, 2024
@siriwatknp
Copy link
Member Author

siriwatknp commented Dec 3, 2024

@oliviertassinari Based on your comment, are you okay with the new prop? Please see this comment instead. I will update this PR if you are okay with @mnajdova suggestion.

@mui-bot
Copy link

mui-bot commented Dec 3, 2024

Netlify deploy preview

IconButton: parsed: +4.52% , gzip: +3.56%
Alert: parsed: +3.99% , gzip: +3.03%
Autocomplete: parsed: +2.44% , gzip: +1.83%
@material-ui/core: parsed: +0.66% , gzip: +0.45%
LoadingButton: parsed: -0.73% 😍, gzip: -0.13% 😍
@material-ui/lab: parsed: 0.00% 😍, gzip: +0.12%

Bundle size report

Details of bundle changes (Toolpad)
Details of bundle changes

Generated by 🚫 dangerJS against 978a40e

@mnajdova
Copy link
Member

mnajdova commented Dec 3, 2024

This PR build on top of the reverted #42987 by adding a new prop enableLoadingWrapper to specifically fix the problem with Google Translation Crash.

Wouldn't it be better to automatically add the span if the loading prop has a boolean value (true/false), and don't add it if it has a nullish value. We can explain in the demos the usage.

@siriwatknp
Copy link
Member Author

This PR build on top of the reverted #42987 by adding a new prop enableLoadingWrapper to specifically fix the problem with Google Translation Crash.

Wouldn't it be better to automatically add the span if the loading prop has a boolean value (true/false), and don't add it if it has a nullish value. We can explain in the demos the usage.

That's a nice suggestion. If I understand correctly, there is no need for the new prop, right. The default value of loading is null which will not render the extra span by default. When loading={boolean}, the span is always there.

@mnajdova
Copy link
Member

mnajdova commented Dec 5, 2024

That's a nice suggestion. If I understand correctly, there is no need for the new prop, right. The default value of loading is null which will not render the extra span by default. When loading={boolean}, the span is always there.

Yes, the downside is that a component cannot alternative between supporting loading or not (at least in terms of working with Google translate). I think that's nice compromise.

@DiegoAndai
Copy link
Member

The default value of loading is null which will not render the extra span by default. When loading={boolean}, the span is always there.

I like this approach 👍🏼 let's add a short explanation in the docs as well.

@siriwatknp siriwatknp requested a review from mnajdova December 6, 2024 03:22
@siriwatknp
Copy link
Member Author

@mnajdova @DiegoAndai Ready for review.

@ZeeshanTamboli
Copy link
Member

@siriwatknp I’ve linked two issues in the description that should be closed when this PR merges, the same as in #44637.

Copy link
Member

@DiegoAndai DiegoAndai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Jun! Thanks for pickling this one back up again.

I think the loadingPosition needs some work, see these examples: https://codesandbox.io/p/sandbox/44637-feedback-1-wtf45k

Screenshot 2024-12-09 at 17 04 09

In these examples users would expect the loading indicator to position itself correctly.

@@ -364,13 +524,22 @@ const Button = React.forwardRef(function Button(inProps, ref) {
endIcon: endIconProp,
focusVisibleClassName,
fullWidth = false,
id: idProp,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's id's prop required for?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for labeling the loader:

const loadingIndicator = loadingIndicatorProp ?? (
  <CircularProgress aria-labelledby={id} color="inherit" size={16} />
);

Comment on lines 186 to 194
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This goes against having atomic classes. I think a better approach would be having:

loadingPositionCenter, loadingPositionStart, loadingPositionEnd classes applied to the root depending on the loadingPosition prop.

Which can be combined with other classes, for example

  • .loadingPositionStart .loadingIndicator { ... } instead of loadingIndicatorStart
  • .loadingPositionStart .startIcon { ... } instead of startIconLoadingStart

Reducing these 5 classes into 3.

We should try to follow the rule of having one class per prop-value combination.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. Removed.


{{"demo": "LoadingIconButton.js"}}

### Badge
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't include the loading prop in the Badge's demo. It should be only about the Badge.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@siriwatknp
Copy link
Member Author

think the loadingPosition needs some work, see these examples: https://codesandbox.io/p/sandbox/44637-feedback-1-wtf45k

The root cause is that there is no icon to provide the space for the loading. I fixed this by render a loadingIconPlaceholder slot when there is no icon on that position.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: button This is the name of the generic UI component, not the React module! new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[material-ui][Button] Button doesn't have the loading props [LoadingButton] Displaying incorrect warning
5 participants