From 44b3a60ba2d39054f4de856d7a3a0a44dd00af18 Mon Sep 17 00:00:00 2001 From: Oliver Baker Date: Thu, 12 Jan 2023 11:37:44 -0600 Subject: [PATCH 1/2] fix(interaction feedback): rework of the udnerlying code for splashes This should fix the missing splashes on buttons, as well as improve performance fixes #401 --- src/components/Button/Button.stories.tsx | 12 +++ .../InteractionFeedback.stories.tsx | 10 +-- .../InteractionFeedback.tsx | 81 ++++++++++++------- 3 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/components/Button/Button.stories.tsx b/src/components/Button/Button.stories.tsx index ce6640038..8b80d104b 100644 --- a/src/components/Button/Button.stories.tsx +++ b/src/components/Button/Button.stories.tsx @@ -25,6 +25,18 @@ BasicButton.args = { color: colors.primaryDark, disabled: false, feedbackType: FeedbackTypes.ripple, + // interactionFeedbackProps: { + // transitionProps: { + // from: { + // opacity: 0.5, + // r: 0, + // }, + // enter: { + // opacity: 0, + // r: 100, + // }, + // }, + // }, isLoading: false, elevation: 1, isProcessing: false, diff --git a/src/components/InteractionFeedback/InteractionFeedback.stories.tsx b/src/components/InteractionFeedback/InteractionFeedback.stories.tsx index 47383f43e..52ba0e361 100644 --- a/src/components/InteractionFeedback/InteractionFeedback.stories.tsx +++ b/src/components/InteractionFeedback/InteractionFeedback.stories.tsx @@ -54,14 +54,14 @@ export const Splash: Story = ({ clamp, }, }; - const interpolationFunctions = { - r: (r: any) => r.to((val: string) => `${Math.abs(parseFloat(val)).toFixed(1)}`), - opacity: (opacity: any) => opacity.to((val: number) => val.toFixed(2)), - }; + // const interpolationFunctions = { + // r: (r: any) => r.to((val: string) => `${Math.abs(parseFloat(val)).toFixed(1)}`), + // opacity: (opacity: any) => opacity.to((val: number) => val.toFixed(2)), + // }; return ( diff --git a/src/components/InteractionFeedback/InteractionFeedback.tsx b/src/components/InteractionFeedback/InteractionFeedback.tsx index 8990e44a2..e74e83ae7 100644 --- a/src/components/InteractionFeedback/InteractionFeedback.tsx +++ b/src/components/InteractionFeedback/InteractionFeedback.tsx @@ -1,4 +1,4 @@ -import { animated, useTransition } from '@react-spring/web'; +import { animated, useSprings } from '@react-spring/web'; import React, { useCallback, useRef, useState } from 'react'; import styled from 'styled-components'; import useResizeObserver from 'use-resize-observer/polyfilled'; @@ -22,6 +22,7 @@ const SVGContainer = styled.svg` type Animation = { cx: string; cy: string; id: string }; type Transition = { r: string } & Animation; + export type InteractionFeedbackProps = { StyledContainer?: StyledSubcomponentType; StyledSVGContainer?: StyledSubcomponentType; @@ -30,23 +31,23 @@ export type InteractionFeedbackProps = { children?: React.ReactNode; color?: string; - interpolationFunctions?: Record any>; + // interpolationFunctions?: Record any>; // TODO add proper type from react-spring - transitionProps?: any; + transitionProps?: Record>; containerRef?: React.RefObject; SVGContainerRef?: React.RefObject; }; -const defaultInterpolationFunctions = { - r: (r: any) => r.to((val: string) => `${Math.abs(parseFloat(val)).toFixed(1)}`), - opacity: (opacity: any) => opacity.to((val: number) => val.toFixed(2)), -}; +// const defaultInterpolationFunctions = { +// r: (r: any) => r.to((val: string) => `${Math.abs(parseFloat(val)).toFixed(1)}`), +// opacity: (opacity: any) => opacity.to((val: number) => val.toFixed(2)), +// }; const defaultTransitionProps = { from: { - r: 0, + r: 20, opacity: 0.5, }, - enter: { + to: { r: 100, opacity: 0, }, @@ -55,7 +56,7 @@ const defaultTransitionProps = { tension: 1000, friction: 20, round: 1, - clamp: false, + clamp: true, }, }; const InteractionFeedback = ({ @@ -68,26 +69,41 @@ const InteractionFeedback = ({ color = colors.primary, children, - interpolationFunctions = defaultInterpolationFunctions, + // interpolationFunctions = defaultInterpolationFunctions, transitionProps = { ...defaultTransitionProps }, }: InteractionFeedbackProps): JSX.Element => { const internalRef = useRef(); const { ref, width = 0, height = 0 } = useResizeObserver(); const [animations, setAnimations] = useState>([]); - const transitions = useTransition(animations, { - keys: (item: Animation) => item.id, - onRest: (item: Transition) => setAnimations(a => a.filter(ani => ani.id === item.id)), - ...transitionProps, - }); - const fragment = transitions((style, item) => { - const circleProps = Object.entries(style).reduce((acc, [key, val]) => { - return { - ...acc, - [key]: interpolationFunctions[key] ? interpolationFunctions[key](val) : val, - }; - }, {}); - return ; + const [springs, springApi] = useSprings( + animations.length, + i => ({ + onStart: () => { + console.log('started'); + }, + onChange: () => { + console.log('m'); + }, + onRest: (result, spring, item) => { + setAnimations(a => a.filter(ani => ani.id === animations[i].id)); + console.log(result, spring, item); + }, + ...transitionProps, + }), + [], + ); + + const fragment = springs.map((style, ind) => { + return ( + + ); }); const mouseDownHandler = useCallback( @@ -99,10 +115,21 @@ const InteractionFeedback = ({ const percentX = (100 * (clientX - boundingRect.left)) / boundingRect.width; const percentY = (100 * (clientY - boundingRect.top)) / boundingRect.height; - setAnimations(a => [...a, { cx: `${percentX}%`, cy: `${percentY}%`, id: randomId(18) }]); + const newAnimation = { + cx: `${percentX}%`, + cy: `${percentY}%`, + id: `${randomId(18)}`, + }; + setAnimations(a => [...a, newAnimation]); + + springApi.start(i => { + if (i === animations.length) { + return transitionProps; + } + }); } }, - [internalRef], + [transitionProps, springApi, animations], ); const handleEventWithAnalytics = useAnalytics(); @@ -138,6 +165,6 @@ const InteractionFeedback = ({ InteractionFeedback.Container = Container; InteractionFeedback.SVGContainer = SVGContainer; InteractionFeedback.defaultTransitionProps = defaultTransitionProps; -InteractionFeedback.defaultInterpolationFunctions = defaultInterpolationFunctions; +// InteractionFeedback.defaultInterpolationFunctions = defaultInterpolationFunctions; export default InteractionFeedback; From 85b28a1e8e59a7bd9875ad234d1358c693d4feb5 Mon Sep 17 00:00:00 2001 From: Oliver Baker Date: Thu, 12 Jan 2023 11:41:39 -0600 Subject: [PATCH 2/2] snapshot --- src/components/InteractionFeedback/InteractionFeedback.tsx | 2 +- .../__tests__/__snapshots__/InteractionFeedback.test.tsx.snap | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/InteractionFeedback/InteractionFeedback.tsx b/src/components/InteractionFeedback/InteractionFeedback.tsx index e74e83ae7..18700ada5 100644 --- a/src/components/InteractionFeedback/InteractionFeedback.tsx +++ b/src/components/InteractionFeedback/InteractionFeedback.tsx @@ -21,7 +21,7 @@ const SVGContainer = styled.svg` `; type Animation = { cx: string; cy: string; id: string }; -type Transition = { r: string } & Animation; +// type Transition = { r: string } & Animation; export type InteractionFeedbackProps = { StyledContainer?: StyledSubcomponentType; diff --git a/src/components/InteractionFeedback/__tests__/__snapshots__/InteractionFeedback.test.tsx.snap b/src/components/InteractionFeedback/__tests__/__snapshots__/InteractionFeedback.test.tsx.snap index a159876ff..c5ca4308d 100644 --- a/src/components/InteractionFeedback/__tests__/__snapshots__/InteractionFeedback.test.tsx.snap +++ b/src/components/InteractionFeedback/__tests__/__snapshots__/InteractionFeedback.test.tsx.snap @@ -31,7 +31,7 @@ exports[`InteractionFeedback Shows InteractionFeedback with default props 1`] = cy="NaN%" fill="#DA4200" opacity="0.5" - r="0" + r="20" />