mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.74k stars 32.24k forks source link

Disabling animations either per-component or globally #10560

Closed tom-james-watson closed 5 years ago

tom-james-watson commented 6 years ago

I find the performance really suffers on some mobile devices whenever any animations are happening.

I'd ideally like to be able to disable animations per component, or if not, globally.

Ideally there'd be an option like so:

<ExpansionPanel animate={false}>
    ...
</ExpansionPanel>

As far as I can tell, this is not currently possible.

Firstly - is there a workaround where I can disable animations with css overrides?

Secondly - should this be considered for being added as a feature?

Your Environment

Tech Version
Material-UI 1.0.0-beta.33
React 16.2.0
browser any on low-powered devices

Thanks in advance!

oliviertassinari commented 6 years ago

is there a workaround where I can disable animations with css overrides?

@tom-james-watson Yes, you can disable the transition with CSS:

const styles = {
  disableTransition: {
    transition: 'none',
  }
};

<ExpansionPanel className={classes.disableTransition} CollapseProps={{ classes: { container: classes.disableTransition }}}>

https://codesandbox.io/s/kwr5xnnq2o

should this be considered for being added as a feature?

I really like the idea of disabling the transition for low-end devices that aren't fast enough to support them. I agree.

xemasiv commented 6 years ago

Hmmm this is helpful, in my app I've seen great improvements in performance by disabling the ripples in some components.

I can see this + #11416 being a great help for developers with end-users on developing countries.

oliviertassinari commented 6 years ago

@tom-james-watson We use theme.transitions.create() almost everywhere to create the transitions, by overriding this method in the theme, you should easily be able to disable the transition globally. Adding the fact that the theme can be nested, you should be able to build a <DisableTransition /> component easily to cherrypick.

@xemasiv The ripple can be disabled globally as documented here: https://material-ui.com/customization/themes/#properties.

jacobweber commented 5 years ago

@oliviertassinari If you have a minute, could you post an example of what the theme.transitions.create() override would look like, to disable transitions globally?

oliviertassinari commented 5 years ago

@jacobweber Yes, of course. You can do the following.

import { createMuiTheme } from '@material-ui/core';

const theme = createMuiTheme({
  props: {
    // Name of the component ⚛️
    MuiButtonBase: {
      // The properties to apply
      disableRipple: true, // No more ripple, on the whole application 💣!
    },
  },
  transitions: {
    // So we have `transition: none;` everywhere
    create: () => 'none',
  },
});

Some peope will want to enable this behavior conditionally, for instance when serving an android user. In these cases, they can dynamically change the theme value.

I think that it would be breat to have a demo in the documentation or at least have this use case listed under the FAQ. Anyone wants to work on it? Thank you!

jacobweber commented 5 years ago

That's great -- thanks so much. In my case I want to disable it for automated browser testing. It can be hard to tell when a transition is completed. So you might find a button, but then it moves before you can click it. This should help with that.

IssueHuntBot commented 5 years ago

@issuehuntfest has funded $40.00 to this issue. See it on IssueHunt

TSMMark commented 5 years ago

In case someone else ends up here as I did, I had to jest mock out the Collapse component to avoid error during snapshot testing Cannot set property 'height' of undefined.

There is probably a better way but I simply mocked it to return its children:

/*
Without mocking Collapse, you'll get an error when rendering the Collapse:
Error: Uncaught [TypeError: Cannot set property 'height' of undefined]
at reportException (.../node_modules/jsdom/lib/jsdom/living/helpers/runtime-script-errors.js:66:24)
at invokeEventListeners (.../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:209:9)
at HTMLUnknownElementImpl._dispatch (.../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
at HTMLUnknownElementImpl.dispatchEvent (.../node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
at HTMLUnknownElementImpl.dispatchEvent (.../node_modules/jsdom/lib/jsdom/living/nodes/HTMLElement-impl.js:30:27)
at HTMLUnknownElement.dispatchEvent (.../node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
at Object.invokeGuardedCallbackDev (.../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1919:16)
at invokeGuardedCallback (.../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:1968:29)
at commitRoot (.../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7655:7)
at completeRoot (.../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:8624:34) TypeError: Cannot set property 'height' of undefined
at Object.Collapse._this.handleEnter [as onEnter] (.../node_modules/@material-ui/core/Collapse/Collapse.js:86:25)
at Transition.performEnter (.../node_modules/@material-ui/core/node_modules/react-transition-group/Transition.js:265:16)
at Transition.updateStatus (.../node_modules/@material-ui/core/node_modules/react-transition-group/Transition.js:238:14)
at Transition.componentDidUpdate (.../node_modules/@material-ui/core/node_modules/react-transition-group/Transition.js:202:10)
at commitLifeCycles (.../node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6435:22)
*/
jest.mock('@material-ui/core/Collapse', () => {
  const RealLibrary = require.requireActual('@material-ui/core/Collapse')
  return class extends RealLibrary.default {
    render () {
      return (<div className='Mocked-Collapse'>
        { this.props.children }
      </div>)
    }
  }
})
oliviertassinari commented 5 years ago

@TSMMark how is this related to this issue? Here is the Collapse source code: https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Collapse/Collapse.js.

TSMMark commented 5 years ago

It is related to

Disabling animations either per-component or globally

Specifically for the ExpansionPanel component, which was referenced by OP. As @jacobweber mentioned, people are arriving here at #10560 when trying to disable animations in test environment. I posted a jest mock to help people in the future if they encounter the same issue as I did with jest & jsdom when using ExpansionPanel.

IssueHuntBot commented 5 years ago

@joshwooding has submitted a pull request. See it on IssueHunt

IssueHuntBot commented 5 years ago

@oliviertassinari has rewarded $36.00 to @joshwooding. See it on IssueHunt