Fix StoryViewer and update spring animations

Co-authored-by: Jamie Kyle <113370520+jamiebuilds-signal@users.noreply.github.com>
This commit is contained in:
automated-signal 2024-09-04 11:56:08 -05:00 committed by GitHub
parent ecb1a4f147
commit a806340f80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 34 additions and 15 deletions

View file

@ -5,6 +5,7 @@ import React from 'react';
import { animated, to as interpolate, useSprings } from '@react-spring/web';
import { random } from 'lodash';
import { Emojify } from './conversation/Emojify';
import { useReducedMotion } from '../hooks/useReducedMotion';
export type PropsType = {
emoji: string;
@ -38,9 +39,11 @@ export function AnimatedEmojiGalore({
emoji,
onAnimationEnd,
}: PropsType): JSX.Element {
const reducedMotion = useReducedMotion();
const [springs] = useSprings(NUM_EMOJIS, i => ({
...to(i, onAnimationEnd),
from: from(i),
immediate: reducedMotion,
config: {
mass: 20,
tension: 120,

View file

@ -2,7 +2,6 @@
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useEffect } from 'react';
import { Globals } from '@react-spring/web';
import classNames from 'classnames';
import type { ViewStoryActionCreatorType } from '../state/ducks/stories';
@ -13,7 +12,6 @@ import { type AppStateType, AppViewType } from '../state/ducks/app';
import { SmartInstallScreen } from '../state/smart/InstallScreen';
import { StandaloneRegistration } from './StandaloneRegistration';
import { usePageVisibility } from '../hooks/usePageVisibility';
import { useReducedMotion } from '../hooks/useReducedMotion';
type PropsType = {
state: AppStateType;
@ -124,14 +122,6 @@ export function App({
document.body.classList.toggle('page-is-visible', isPageVisible);
}, [isPageVisible]);
// A11y settings for react-spring
const prefersReducedMotion = useReducedMotion();
useEffect(() => {
Globals.assign({
skipAnimation: prefersReducedMotion,
});
}, [prefersReducedMotion]);
return (
<div
className={classNames({

View file

@ -6,6 +6,7 @@ import { animated, useSpring } from '@react-spring/web';
import { random } from 'lodash';
import { v4 as uuid } from 'uuid';
import { Emojify } from './conversation/Emojify';
import { useReducedMotion } from '../hooks/useReducedMotion';
export type PropsType = {
values: Array<string>;
@ -124,7 +125,9 @@ export function AnimatedEmoji({
}: AnimatedEmojiProps): JSX.Element {
const height = EMOJI_HEIGHT * toScale;
const reducedMotion = useReducedMotion();
const { rotate, x, y } = useSpring({
immediate: reducedMotion,
from: {
rotate: fromRotate,
x: fromX,
@ -142,6 +145,7 @@ export function AnimatedEmoji({
// These styles animate faster than Y.
// Reactions toasts animate with opacity so harmonize with that.
const { scale } = useSpring({
immediate: reducedMotion,
from: {
scale: 0.5,
},

View file

@ -14,6 +14,7 @@ import { ModalHost } from './ModalHost';
import { drop } from '../util/drop';
import * as log from '../logging/log';
import { usePrevious } from '../hooks/usePrevious';
import { useReducedMotion } from '../hooks/useReducedMotion';
export type PropsType = {
readonly i18n: LocalizerType;
@ -174,6 +175,8 @@ export function CallingRaisedHandsListButton({
}: CallingRaisedHandsListButtonPropsType): JSX.Element | null {
const [isVisible, setIsVisible] = React.useState(raisedHandsCount > 0);
const reducedMotion = useReducedMotion();
// eslint-disable-next-line react-hooks/exhaustive-deps -- FIXME
const [opacitySpringProps, opacitySpringApi] = useSpring(
{
@ -186,6 +189,7 @@ export function CallingRaisedHandsListButton({
// eslint-disable-next-line react-hooks/exhaustive-deps -- FIXME
const [scaleSpringProps, scaleSpringApi] = useSpring(
{
immediate: reducedMotion,
from: { scale: 0.9 },
to: { scale: 1 },
config: BUTTON_SCALE_SPRING_CONFIG,

View file

@ -18,6 +18,7 @@ import { useIsMounted } from '../hooks/useIsMounted';
import type { LocalizerType } from '../types/I18N';
import { usePrevious } from '../hooks/usePrevious';
import { difference } from '../util/setUtil';
import { useReducedMotion } from '../hooks/useReducedMotion';
const DEFAULT_LIFETIME = 5000;
const DEFAULT_TRANSITION_FROM = {
@ -225,7 +226,10 @@ export function CallingToastProvider({
const toastsRemoved = difference(prevToasts, curToasts);
const toastsAdded = difference(curToasts, prevToasts);
const reducedMotion = useReducedMotion();
const transitions = useTransition(toasts, {
immediate: reducedMotion,
from: item => {
const enteringItemIndex = toasts.findIndex(
toast => toast.key === item.key

View file

@ -30,6 +30,7 @@ import { drop } from '../util/drop';
import { isCmdOrCtrl } from '../hooks/useKeyboardShortcuts';
import type { ForwardMessagesPayload } from '../state/ducks/globalModals';
import { ForwardMessagesModalType } from './ForwardMessagesModal';
import { useReducedMotion } from '../hooks/useReducedMotion';
export type PropsType = {
children?: ReactNode;
@ -322,9 +323,12 @@ export function Lightbox({
const thumbnailsMarginInlineStart =
0 - (selectedIndex * THUMBNAIL_FULL_WIDTH + THUMBNAIL_WIDTH / 2);
const reducedMotion = useReducedMotion();
// eslint-disable-next-line react-hooks/exhaustive-deps -- FIXME
const [thumbnailsStyle, thumbnailsAnimation] = useSpring(
{
immediate: reducedMotion,
config: THUMBNAIL_SPRING_CONFIG,
to: {
marginInlineStart: thumbnailsMarginInlineStart,

View file

@ -4,6 +4,7 @@
import { animated, useSpring } from '@react-spring/web';
import classNames from 'classnames';
import React, { useCallback } from 'react';
import { useReducedMotion } from '../hooks/useReducedMotion';
const SPRING_CONFIG = {
mass: 0.5,
@ -27,9 +28,11 @@ export type ButtonProps = {
export const PlaybackButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
function ButtonInner(props, ref) {
const { mod, label, variant, onClick, context, visible = true } = props;
const reducedMotion = useReducedMotion();
// eslint-disable-next-line react-hooks/exhaustive-deps -- FIXME
const [animProps] = useSpring(
{
immediate: reducedMotion,
config: SPRING_CONFIG,
to: { scale: visible ? 1 : 0 },
},

View file

@ -5,6 +5,7 @@ import classNames from 'classnames';
import React, { useCallback, useState } from 'react';
import { animated, useSpring } from '@react-spring/web';
import type { LocalizerType } from '../types/Util';
import { useReducedMotion } from '../hooks/useReducedMotion';
const SPRING_CONFIG = {
mass: 0.5,
@ -30,10 +31,12 @@ export function PlaybackRateButton({
onClick,
}: Props): JSX.Element {
const [isDown, setIsDown] = useState(false);
const reducedMotion = useReducedMotion();
// eslint-disable-next-line react-hooks/exhaustive-deps -- FIXME
const [animProps] = useSpring(
{
immediate: reducedMotion,
config: SPRING_CONFIG,
to: isDown ? { scale: 1.3 } : { scale: visible ? 1 : 0 },
},

View file

@ -47,6 +47,7 @@ import { isWhitespace, trim } from '../util/whitespaceStringUtil';
import { UserText } from './UserText';
import { Tooltip, TooltipPlacement } from './Tooltip';
import { offsetDistanceModifier } from '../util/popperUtil';
import { useReducedMotion } from '../hooks/useReducedMotion';
export enum EditState {
None = 'None',
@ -824,8 +825,9 @@ function UsernameLinkTooltip({
children: React.ReactNode;
i18n: LocalizerType;
}) {
const reducedMotion = useReducedMotion();
const animatedStyles = useSpring({
from: { opacity: 0, scale: 0.25 },
from: { opacity: 0, scale: reducedMotion ? 1 : 0.25 },
to: { opacity: 1, scale: 1 },
config: { mass: 1, tension: 280, friction: 25 },
delay: 200,

View file

@ -29,10 +29,6 @@ export const StoryProgressSegment = memo(function StoryProgressSegment({
const [progressBarStyle] = useSpring(() => {
return {
// Override default value from `Globals` to ignore "Reduce Motion" setting.
// This animation is important for progressing through stories and is minor
// enough that it shouldn't cause issues for users with sensitivity to motion.
skipAnimation: false,
immediate: index !== currentIndex,
// Pause while we are waiting for a valid duration
pause: !playing || !isValidDuration(duration),

View file

@ -13,6 +13,7 @@ import type { LocalizerType, ThemeType } from '../../types/Util';
import type { ConversationType } from '../../state/ducks/conversations';
import type { PreferredBadgeSelectorType } from '../../state/selectors/badges';
import { drop } from '../../util/drop';
import { useReducedMotion } from '../../hooks/useReducedMotion';
const MAX_AVATARS_COUNT = 3;
@ -87,9 +88,11 @@ function TypingBubbleAvatar({
i18n: LocalizerType;
theme: ThemeType;
}): ReactElement | null {
const reducedMotion = useReducedMotion();
// eslint-disable-next-line react-hooks/exhaustive-deps -- FIXME
const [springProps, springApi] = useSpring(
{
immediate: reducedMotion,
config: SPRING_CONFIG,
from: shouldAnimate
? AVATAR_ANIMATION_PROPS[visible ? 'hidden' : 'visible']

View file

@ -4,6 +4,7 @@
import { useState, useCallback } from 'react';
import type { SpringValues } from '@react-spring/web';
import { useChain, useSpring, useSpringRef } from '@react-spring/web';
import { useReducedMotion } from './useReducedMotion';
export type ModalConfigType = {
opacity: number;
@ -33,6 +34,7 @@ export function useAnimated(
modalStyles: SpringValues<ModalConfigType>;
overlayStyles: SpringValues<ModalConfigType>;
} {
const reducedMotion = useReducedMotion();
const [state, setState] = useState(ModalState.Opening);
const shouldShowModal =
state === ModalState.Open || state === ModalState.Opening;
@ -41,6 +43,7 @@ export function useAnimated(
const modalRef = useSpringRef();
const modalStyles = useSpring({
immediate: reducedMotion,
from: getFrom(shouldShowModal),
to: getTo(shouldShowModal),
onRest: () => {