From 2297687ae1ad6828bbe7cc4f734b81a5d9a5268e Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Wed, 5 Jun 2024 15:01:50 +0100 Subject: [PATCH] Chore: Ensure all `react-transition-group` animations use `nodeRef` (#88604) * ensure all react-transition-group animations pass nodeRef * clone children instead of wrapping in div * remove div wrapper * revert back to div --- .../components/transitions/FadeTransition.tsx | 16 ++++++++++++---- .../transitions/SlideOutTransition.tsx | 16 ++++++++++++---- public/app/core/components/Animations/FadeIn.tsx | 5 ++++- .../app/core/components/Animations/SlideDown.tsx | 6 ++++-- public/app/features/explore/LiveTailButton.tsx | 6 ++++-- .../Logs/utils/LogsCrossFadeTransition.tsx | 8 +++++--- 6 files changed, 41 insertions(+), 16 deletions(-) diff --git a/packages/grafana-ui/src/components/transitions/FadeTransition.tsx b/packages/grafana-ui/src/components/transitions/FadeTransition.tsx index 501a0dfe40e..4127dcbd60c 100644 --- a/packages/grafana-ui/src/components/transitions/FadeTransition.tsx +++ b/packages/grafana-ui/src/components/transitions/FadeTransition.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import React from 'react'; +import React, { useRef } from 'react'; import { CSSTransition } from 'react-transition-group'; import { GrafanaTheme2 } from '@grafana/data'; @@ -7,7 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '../../themes'; type Props = { - children: React.ReactNode; + children: React.ReactElement; visible: boolean; duration?: number; }; @@ -15,10 +15,18 @@ type Props = { export function FadeTransition(props: Props) { const { visible, children, duration = 250 } = props; const styles = useStyles2(getStyles, duration); + const transitionRef = useRef(null); return ( - - {children} + + {React.cloneElement(children, { ref: transitionRef })} ); } diff --git a/packages/grafana-ui/src/components/transitions/SlideOutTransition.tsx b/packages/grafana-ui/src/components/transitions/SlideOutTransition.tsx index a12a4ba1700..d6241042143 100644 --- a/packages/grafana-ui/src/components/transitions/SlideOutTransition.tsx +++ b/packages/grafana-ui/src/components/transitions/SlideOutTransition.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import React from 'react'; +import React, { useRef } from 'react'; import { CSSTransition } from 'react-transition-group'; import { GrafanaTheme2 } from '@grafana/data'; @@ -7,7 +7,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '../../themes'; type Props = { - children: React.ReactNode; + children: React.ReactElement; visible: boolean; size: number; @@ -18,10 +18,18 @@ type Props = { export function SlideOutTransition(props: Props) { const { visible, children, duration = 250, horizontal, size } = props; const styles = useStyles2(getStyles, duration, horizontal ? 'width' : 'height', size); + const transitionRef = useRef(null); return ( - - {children} + + {React.cloneElement(children, { ref: transitionRef })} ); } diff --git a/public/app/core/components/Animations/FadeIn.tsx b/public/app/core/components/Animations/FadeIn.tsx index 6794728726a..6aa086a8ed5 100644 --- a/public/app/core/components/Animations/FadeIn.tsx +++ b/public/app/core/components/Animations/FadeIn.tsx @@ -1,4 +1,4 @@ -import React, { CSSProperties } from 'react'; +import React, { CSSProperties, useRef } from 'react'; import Transition, { ExitHandler } from 'react-transition-group/Transition'; interface Props { @@ -10,6 +10,7 @@ interface Props { } export const FadeIn = (props: Props) => { + const transitionRef = useRef(null); const defaultStyle: CSSProperties = { transition: `opacity ${props.duration}ms linear`, opacity: 0, @@ -28,9 +29,11 @@ export const FadeIn = (props: Props) => { timeout={props.duration} unmountOnExit={props.unmountOnExit || false} onExited={props.onExited} + nodeRef={transitionRef} > {(state) => (
= ({ children, in: inProp, maxHeight = defaultMaxHeight, style = defaultStyle }) => { + const transitionRef = useRef(null); // There are 4 main states a Transition can be in: // ENTERING, ENTERED, EXITING, EXITED // https://reactcommunity.or[g/react-transition-group/ @@ -35,13 +36,14 @@ export const SlideDown: FC = ({ children, in: inProp, maxHeight = default }; return ( - + {(state) => (
{children}
diff --git a/public/app/features/explore/LiveTailButton.tsx b/public/app/features/explore/LiveTailButton.tsx index 8d6decc3e57..81d71a18b6e 100644 --- a/public/app/features/explore/LiveTailButton.tsx +++ b/public/app/features/explore/LiveTailButton.tsx @@ -1,5 +1,5 @@ import { css } from '@emotion/css'; -import React from 'react'; +import React, { useRef } from 'react'; import { CSSTransition } from 'react-transition-group'; import { Tooltip, ButtonGroup, ToolbarButton } from '@grafana/ui'; @@ -15,6 +15,7 @@ type LiveTailButtonProps = { }; export function LiveTailButton(props: LiveTailButtonProps) { + const transitionRef = useRef(null); const { start, pause, resume, isLive, isPaused, stop, splitted } = props; const buttonVariant = isLive && !isPaused ? 'active' : 'canvas'; const onClickMain = isLive ? (isPaused ? resume : pause) : start; @@ -46,9 +47,10 @@ export function LiveTailButton(props: LiveTailButtonProps) { exit: styles.stopButtonExit, exitActive: styles.stopButtonExitActive, }} + nodeRef={transitionRef} > Stop and exit the live stream} placement="bottom"> - + diff --git a/public/app/features/explore/Logs/utils/LogsCrossFadeTransition.tsx b/public/app/features/explore/Logs/utils/LogsCrossFadeTransition.tsx index 8ccc6eba5b5..209fa67ccc7 100644 --- a/public/app/features/explore/Logs/utils/LogsCrossFadeTransition.tsx +++ b/public/app/features/explore/Logs/utils/LogsCrossFadeTransition.tsx @@ -1,6 +1,6 @@ import { css } from '@emotion/css'; import memoizeOne from 'memoize-one'; -import React from 'react'; +import React, { useRef } from 'react'; import { CSSTransition } from 'react-transition-group'; const transitionDuration = 500; @@ -39,7 +39,7 @@ const getStyles = memoizeOne(() => { }); type Props = { - children: React.ReactNode; + children: React.ReactElement; visible: boolean; }; @@ -49,6 +49,7 @@ type Props = { */ export function LogsCrossFadeTransition(props: Props) { const { visible, children } = props; + const transitionRef = useRef(null); const styles = getStyles(); return ( - {children} +
{children}
); }