reactjs / react-transition-group

An easy way to perform animations when a React component enters or leaves the DOM
https://reactcommunity.org/react-transition-group/
Other
10.15k stars 650 forks source link

Accessibility, add support for prefers-reduced-motion #861

Open aguscha333 opened 1 year ago

aguscha333 commented 1 year ago

It would be a really good improvement if the library had more support for accessibility. One very important aspect when using animations is that not everyone wants to see them and for some it might have a negative impact.

One of the tools we can use to make this better is prefers-reduced-motion to bypass the transition all together.

Technically one can do this externally by getting that value with something like this hook use-reduced-motion and when it is true set the timeout to 0. But it would be much better if the library supported it by default and has a prop called ignorePrefersReducedMotion if people want to go out of their way to make it inaccessible.

I know this change would be breaking because it would change how the transitions work by default but it is very important for accessibility.

A more conservative approach would be to add the functionality turned off by default although less people would make use of it 😞.

In any case, adding some docs front and center about this feature should help educate people using the library and make products using this library more accessible.

matt-greenfield-15 commented 7 months ago

I have achieved this for the CSSTransition component by using @media (prefers-reduced-motion) { in the CSS. e.g.

.panel-enter {
  opacity: 0;
}

.panel-enter-active {
  opacity: 1;
  transition: opacity 200ms ease-out;
}

.panel-exit {
  opacity: 1;
}

.panel-exit-active {
  opacity: 0;
  transition: opacity 50ms ease-in;
}

/* 
  Users can set their OS to reduce motion, which will disable animations.
  on macOS, this is located in System Preferences > Accessibility > Display > Reduce motion
*/
@media (prefers-reduced-motion) {
  .panel-enter-active,
  .panel-exit-active {
    transition: none;
  }
}