Fix StoryViewer and update spring animations
Co-authored-by: Jamie Kyle <113370520+jamiebuilds-signal@users.noreply.github.com>
This commit is contained in:
parent
ecb1a4f147
commit
a806340f80
12 changed files with 34 additions and 15 deletions
|
@ -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,
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 },
|
||||
},
|
||||
|
|
|
@ -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 },
|
||||
},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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: () => {
|
||||
|
|
Loading…
Reference in a new issue