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

[SpeedDial] Allow tooltip to always be displayed #12590

Merged
merged 14 commits into from
Sep 3, 2018

Conversation

hashwin
Copy link
Contributor

@hashwin hashwin commented Aug 20, 2018

This is an attempt to rectify the issues that were present in #11103

The logic here is that since the positioning of the tooltip was incorrect due to the rendering time of the SpeedDialAction that comes in via a transition (plus an optional delay given by the delay prop).

This POC shows that the tooltips are indeed rendered in the correct position if there is a timeout given.

@mbrookes please take a look as you reviewed the previous PR. Thanks.

@oliviertassinari oliviertassinari added the package: lab Specific to @mui/lab label Aug 20, 2018
this.setState({ tooltipOpen: true });
};

componentDidUpdate = prevProps => {
if (!this.props.tooltipAlwaysOpen) return;
if (prevProps.open === this.props.open) return;
Copy link
Member

Choose a reason for hiding this comment

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

You could perhaps combine these two line if (!a || b === c) return;

if (!this.props.open && this.state.tooltipOpen) {
this.setState({ tooltipOpen: false });
} else if (!this.state.tooltipOpen) {
setTimeout(() => this.setState({ tooltipOpen: true }), this.props.delay + 100);
Copy link
Member

Choose a reason for hiding this comment

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

You'll need to clear the timeout in componentWillUnmount

/**
* Option to always display the tooltip (usually applicable on mobile)
*/
tooltipAlwaysOpen: PropTypes.bool,
Copy link
Member

Choose a reason for hiding this comment

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

Lets go with tooltipOpen for brevity.

@mbrookes
Copy link
Member

@hashwin Great start!

Did you want to add a docs demo? You could copy it over from #11103...

@hashwin
Copy link
Contributor Author

hashwin commented Aug 26, 2018

@mbrookes I updated the PR with the changes you requested.

@mbrookes mbrookes dismissed their stale review August 27, 2018 00:55

Changes submitted

@hashwin
Copy link
Contributor Author

hashwin commented Aug 30, 2018

@mbrookes good to go?


The SpeedDialActions tooltips can be be displayed persistently so that users don't have to long-press in order to see the tooltip on touch devices.

It is enabled here across all devices for demo purposes, but in production could use the isTouch logic to conditionally set the property.
Copy link
Member

Choose a reason for hiding this comment

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

- but in production could use the isTouch logic
+ but in production it could use the `isTouch` logic

Not sure about the typo but the formatting change would be nice.

Copy link
Member

Choose a reason for hiding this comment

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

Not really a typo, but yours is grammatically clearer. Agree on the formatting.

@eps1lon
Copy link
Member

eps1lon commented Aug 30, 2018

Have you considered using shouldComponentUpdate instead of checking for changes in various functions?

@hashwin
Copy link
Contributor Author

hashwin commented Aug 30, 2018

@eps1lon shouldComponentUpdate will decide whether the component re-renders or not. I don't think this should be decided by any of the logic encapsulated in this PR by this feature. All that is needed to be done is to mark the tooltips to be rendered after a certain delay, any other rendering within the components should work exactly as it was before.

this.setState({ tooltipOpen: false });
};

handleTooltipOpen = () => {
if (this.props.tooltipOpen) return;
this.setState({ tooltipOpen: true });
Copy link
Member

Choose a reason for hiding this comment

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

@hashwin I was just looking at this and this seems brittle since other methods can still change the state of tooltipOpen. Not sure if we can do anything about this though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see your point, but yeah I don't really see another way of handling this without the state and state itself can be changed from anywhere in the component. In fact, we need to manually set the state here for this feature to work: https://github.com/mui-org/material-ui/pull/12590/files#diff-3c8c197bf9114d5f5a42f05daae04497R59

One thing we can maybe do here is to change the method name from handleTooltipOpen to something like onHover so that it explicitly says that nothing should be done on hover if the prop tooltipOpen is given. Thoughts?

componentDidUpdate = prevProps => {
if (!this.props.tooltipOpen || prevProps.open === this.props.open) return;
if (!this.props.open && this.state.tooltipOpen) {
this.setState({ tooltipOpen: false });
Copy link
Member

Choose a reason for hiding this comment

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

Do you see a way to move this to getDerivedStateFromProps and save a rendercycle?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@hashwin
Copy link
Contributor Author

hashwin commented Sep 3, 2018

Hi @mbrookes @eps1lon, anything still holding this up?

Copy link
Member

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

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

Just some minor stuff. I would still like to get a successful CI run although that might be not in your power.

state.tooltipOpen = false;
}
return state;
};
Copy link
Member

Choose a reason for hiding this comment

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

That is not how getDerivedStateFromProps works.

Return null for no change or an object that should be merged.

}
};

componentWillUnmount = () => this.timeout && clearTimeout(this.timeout);
Copy link
Member

Choose a reason for hiding this comment

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

Just call clearTimeout. It won't complain about non-ids but will cause issues in browsers that actually use 0 as ids.

@mbrookes mbrookes merged commit 2f381bf into mui:master Sep 3, 2018
@mbrookes
Copy link
Member

mbrookes commented Sep 3, 2018

@hashwin Nice first contribution! 👍

@mbrookes mbrookes added the component: speed dial This is the name of the generic UI component, not the React module! label Sep 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: speed dial This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants