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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce motion hook #811

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

Reduce motion hook #811

infiniteluke opened this issue Sep 12, 2019 · 8 comments
Labels

Comments

@infiniteluke
Copy link

@infiniteluke 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;
};
@drcmda

This comment has been minimized.

Copy link
Collaborator

@drcmda 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

This comment has been minimized.

Copy link
Member

@aleclarson aleclarson commented Sep 12, 2019

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

This comment has been minimized.

Copy link
Author

@infiniteluke 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

This comment has been minimized.

Copy link
Collaborator

@drcmda 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

This comment has been minimized.

Copy link
Author

@infiniteluke infiniteluke commented Sep 12, 2019

Thanks for the feedback and encouragement!

@infiniteluke

This comment has been minimized.

Copy link
Author

@infiniteluke 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

This comment has been minimized.

Copy link
Author

@infiniteluke infiniteluke commented Oct 5, 2019

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

This comment has been minimized.

Copy link
Author

@infiniteluke infiniteluke commented Oct 9, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can鈥檛 perform that action at this time.