From 7932d7a47176236337ab242072b502e2dd46b653 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 31 Oct 2022 11:46:17 -0400 Subject: [PATCH] Disable animations for users that prefer reduced motion --- src/room/InCallView.tsx | 9 +++++++- src/room/PTTButton.tsx | 9 +++++++- src/usePrefersReducedMotion.ts | 42 ++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/usePrefersReducedMotion.ts diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 645213c..d50b06f 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -60,6 +60,7 @@ import { useAudioOutputDevice } from "../video-grid/useAudioOutputDevice"; import { widget, ElementWidgetActions } from "../widget"; import { useJoinRule } from "./useJoinRule"; import { useUrlParams } from "../UrlParams"; +import { usePrefersReducedMotion } from "../usePrefersReducedMotion"; const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {}); // There is currently a bug in Safari our our code with cloning and sending MediaStreams @@ -265,6 +266,8 @@ export function InCallView({ [] ); + const prefersReducedMotion = usePrefersReducedMotion(); + const renderContent = (): JSX.Element => { if (items.length === 0) { return ( @@ -292,7 +295,11 @@ export function InCallView({ } return ( - + {({ item, ...rest diff --git a/src/room/PTTButton.tsx b/src/room/PTTButton.tsx index 306a331..3551cfa 100644 --- a/src/room/PTTButton.tsx +++ b/src/room/PTTButton.tsx @@ -22,6 +22,7 @@ import styles from "./PTTButton.module.css"; import { ReactComponent as MicIcon } from "../icons/Mic.svg"; import { useEventTarget } from "../useEvents"; import { Avatar } from "../Avatar"; +import { usePrefersReducedMotion } from "../usePrefersReducedMotion"; interface Props { enabled: boolean; @@ -159,8 +160,14 @@ export const PTTButton: React.FC = ({ // TODO: We will need to disable this for a global PTT hotkey to work useEventTarget(window, "blur", unhold); + const prefersReducedMotion = usePrefersReducedMotion(); const { shadow } = useSpring({ - shadow: (Math.max(activeSpeakerVolume, -70) + 70) * 0.6, + immediate: prefersReducedMotion, + shadow: prefersReducedMotion + ? activeSpeakerUserId + ? 17 + : 0 + : (Math.max(activeSpeakerVolume, -70) + 70) * 0.6, config: { clamp: true, tension: 300, diff --git a/src/usePrefersReducedMotion.ts b/src/usePrefersReducedMotion.ts new file mode 100644 index 0000000..640b549 --- /dev/null +++ b/src/usePrefersReducedMotion.ts @@ -0,0 +1,42 @@ +/* +Copyright 2022 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { useCallback, useRef, useState } from "react"; + +import { useEventTarget } from "./useEvents"; + +/** + * @returns Whether the user has requested reduced motion. + */ +export const usePrefersReducedMotion = () => { + const mediaQuery = useRef(); + if (mediaQuery.current === undefined) + mediaQuery.current = matchMedia("(prefers-reduced-motion)"); + + const [prefersReducedMotion, setPrefersReducedMotion] = useState( + mediaQuery.current.matches + ); + useEventTarget( + mediaQuery.current!, + "change", + useCallback( + () => setPrefersReducedMotion(mediaQuery.current!.matches), + [setPrefersReducedMotion] + ) + ); + + return prefersReducedMotion; +};