Skip to content

Reduce motion hook #811

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

Closed
infiniteluke opened this issue Sep 12, 2019 · 9 comments
Closed

Reduce motion hook #811

infiniteluke opened this issue Sep 12, 2019 · 9 comments
Labels
kind: request New feature or request that should be actioned

Comments

@infiniteluke
Copy link

infiniteluke commented Sep 12, 2019

🚀 Feature Proposal

useReducedMotion a small hook that indicates whether a user's OS is configured to "Reduce motion" for accessibility purposes.

Motivation

Animation is awesome! But, it makes some people sick. Vestibular dysfunction, a balance disorder of the inner ear, is surprisingly common among US adults. A study from the early 2000's found that approximately 69 million Americans had vestibular dysfunction which results in vertigo, nausea, migraines and hearing loss. Many people affected by vestibular dysfunction will choose to set the "Reduce motion" setting in their OS. In macOS it's found in the accessibility settings.

reduce motion setting is macos

Maybe this should live in user land, but it being shipped with react-spring and featuring it in the docs would encourage developers to build more accessible sites. I'm happy to publish it separately but wanted to drop it in here first to get your thoughts.

Example

Usage Example

https://lukeherrington.com/posts/springtime-in-react-town/#too-much-of-a-good-spring

Proposed Implementation

Open to suggestions here:

const useReducedMotion = () => {
  const [matches, setMatch] = React.useState(false);
  React.useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
    setMatch(mediaQuery.matches);
    const handleChange = () => {
      setMatch(mediaQuery.matches);
    };
    mediaQuery.addEventListener('change', handleChange);
    return () => {
      mediaQuery.removeEventListener('change', handleChange);
    };
  }, []);
  return matches;
};
@infiniteluke infiniteluke added the kind: request New feature or request that should be actioned label Sep 12, 2019
@drcmda
Copy link
Member

drcmda commented Sep 12, 2019

that was an interesting article! and yes i think such a hook would help a lot, but don't you think it should live in its own place, so that it could be of more generic use to others? spring is not tied to a single platform, it's more like a building block or tool that people can use on their specific platforms together with other tools.

i remember that we had similar requests before (switching off animation completely for node testing etc) and i believe v9 will ship with a way to globally alter all springs system-wide @aleclarson

@aleclarson
Copy link
Contributor

There's no simple way to lessen the motion of animations atm, but you can disable animations entirely in v9.

import {Globals} from 'react-spring'

const MyApp = () => {
	const prefersReducedMotion = useReducedMotion()

	React.useEffect(() => {
		Globals.assign({
			skipAnimation: prefersReducedMotion,
		})
	}, [prefersReducedMotion])

	return <div />
}

@infiniteluke
Copy link
Author

infiniteluke commented Sep 12, 2019

@drcmda Thanks for the response and thanks for the amazing work! Agreed about x-platform, and perhaps that's an abstraction I should consider if I release this as a package. Otherwise, it's pretty easy to copy/paste or just write yourself.

@aleclarson I wasn't aware of the Globals object in v9. I love it! That's quite concise and I think I'll add that to my article.

Re: lessening animations: That would be a hard problem to solve in the lib because everyone's heuristics for lessen could be different. perhaps exposing more API in useSpring would allow people to do that themselves.

Something like this could work, but kind of muddles the API:

const props = useSpring({
  to: {
    scale: 1.5
  },
  reducedMotionTo: {
    scale: 1.1
  }
});

The existence of reducedMotionTo would signal to react-spring that it should check the "reduce motion" setting for the given platform for that setting. Or perhaps a Global reduceMotion setting could be added which would conditionally use toReduced and warn/throw if a user hasn't defined it in their spring.

Keeping a concise API is really important for a library, so I'm happy to do this by hand using some conditionals:

style={{
  transform: reduceMotion ? 'scale(1.1)' : 'scale(1.5)',
}}

Considering how common vestibular dysfunctions are, putting a solution for this in the library or even mentioning accessible animation techniques/libraries in the docs would make the world more inclusive!

Would you be open to a PR for the react-spring website about accessibility and animations?

Do you think a user-land cross platform useReducedMotion hook would be useful or will this be handled in core eventually?

Thanks for your time!

@drcmda
Copy link
Member

drcmda commented Sep 12, 2019

My feeling is go for it, we could help promoting it. But once it lives in its own npm space as a separate package it can be useful to other people, too, which would be nice.

By that time a small section about accessibility would be welcome here imo.

@infiniteluke
Copy link
Author

infiniteluke commented Sep 12, 2019

Thanks for the feedback and encouragement!

@infiniteluke
Copy link
Author

infiniteluke commented Oct 4, 2019

Hey @drcmda - I am close to releasing a hook based package for this that takes care of web/native. I'll release it on NPM after I get tests running and get some example apps built in codesandbox/expo snack. I also will open a PR for a small snippet about a11y on the website in the coming weeks.

Here's the lib:
https://github.com/infiniteluke/react-reduce-motion

Thanks again for the feedback.

edit: oops, now the repo is public

@infiniteluke
Copy link
Author

It's published 🎉 https://www.npmjs.com/package/react-reduce-motion

The doc site PR will be up in the next couple of days 👍🏻

@infiniteluke
Copy link
Author

I have opened pmndrs/react-spring.io#31 to discuss the documentation change.

@infiniteluke
Copy link
Author

pmndrs/react-spring.io#36 would add an a11y section to the site. posting here for visibility and review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: request New feature or request that should be actioned
Projects
None yet
Development

No branches or pull requests

3 participants