From 148807879b23b8a9f72ed2b893df2ccd98823019 Mon Sep 17 00:00:00 2001 From: Peng Xiao Date: Tue, 27 Feb 2024 14:55:33 +0000 Subject: [PATCH] refactor(component): use react-transition-state to simplify exit animation (#5923) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **User description** use react-transition-state to simplify exit animation ___ ## **Type** enhancement ___ ## **Description** - Integrated `react-transition-state` for managing animations in `ResizePanel` and `CMDKModal` components, simplifying the code and improving maintainability. - Introduced a shared animation timeout variable to standardize animation durations across components. - Added `react-transition-state` to dependencies to enable the new animation handling. ___ ## **Changes walkthrough**
Relevant files
Enhancement
resize-panel.tsx
Integrate `react-transition-state` for Resize Panel Animations

packages/frontend/component/src/components/resize-panel/resize-panel.tsx
  • Introduced useTransition hook from react-transition-state for managing
    animations.
  • Added a constant for animation timeout and applied it to the
    transition.
  • Utilized the transition state to toggle the open state of the resize
    panel.
  • +12/-0   
    modal.css.ts
    Use Variable for Animation Timeout in Modal CSS                   

    packages/frontend/core/src/components/pure/cmdk/modal.css.ts
  • Created a variable for animation timeout.
  • Updated animation durations to use the new timeout variable.
  • +6/-3     
    modal.tsx
    Simplify CMDK Modal Animation with `react-transition-state`

    packages/frontend/core/src/components/pure/cmdk/modal.tsx
  • Replaced custom animation state management with useTransition hook.
  • Removed old animation state logic and simplified the component.
  • Added animation timeout variable and applied it to the transition.
  • +13/-33 
    Dependencies
    package.json
    Add `react-transition-state` Dependency                                   

    packages/frontend/core/package.json - Added `react-transition-state` as a dependency.
    +1/-0     
    ___ > ✨ **PR-Agent usage**: >Comment `/help` on the PR to get a list of all available PR-Agent tools and their descriptions --- packages/frontend/component/package.json | 1 + .../resize-panel/resize-panel.css.ts | 8 ++-- .../components/resize-panel/resize-panel.tsx | 12 +++++ packages/frontend/core/package.json | 1 + .../src/components/pure/cmdk/modal.css.ts | 9 ++-- .../core/src/components/pure/cmdk/modal.tsx | 46 ++++++------------- yarn.lock | 12 +++++ 7 files changed, 50 insertions(+), 39 deletions(-) diff --git a/packages/frontend/component/package.json b/packages/frontend/component/package.json index 5599031546..24562700c6 100644 --- a/packages/frontend/component/package.json +++ b/packages/frontend/component/package.json @@ -65,6 +65,7 @@ "react-is": "^18.2.0", "react-paginate": "^8.2.0", "react-router-dom": "^6.22.1", + "react-transition-state": "^2.1.1", "react-virtuoso": "~4.6.3", "rxjs": "^7.8.1", "swr": "^2.2.5", diff --git a/packages/frontend/component/src/components/resize-panel/resize-panel.css.ts b/packages/frontend/component/src/components/resize-panel/resize-panel.css.ts index bc3198c1ab..655524ac8e 100644 --- a/packages/frontend/component/src/components/resize-panel/resize-panel.css.ts +++ b/packages/frontend/component/src/components/resize-panel/resize-panel.css.ts @@ -5,6 +5,7 @@ export const resizeHandleOffsetVar = createVar('resize-handle-offset'); export const resizeHandleVerticalPadding = createVar( 'resize-handle-vertical-padding' ); +export const animationTimeout = createVar(); export const root = style({ vars: { [panelWidthVar]: '256px', @@ -30,13 +31,14 @@ export const root = style({ marginRight: `calc(${panelWidthVar} * -1)`, }, '&[data-enable-animation="true"]': { - transition: 'margin-left .3s .05s, margin-right .3s .05s, width .3s .05s', + transition: `margin-left ${animationTimeout} .05s, margin-right ${animationTimeout} .05s, width ${animationTimeout} .05s`, }, '&[data-is-floating="false"][data-transparent=true]': { backgroundColor: 'transparent', }, - '&[data-enable-animation="false"][data-open="false"]': { - display: 'none', + '&[data-transition-state="exited"]': { + // avoid focus on hidden panel + visibility: 'hidden', }, }, }); diff --git a/packages/frontend/component/src/components/resize-panel/resize-panel.tsx b/packages/frontend/component/src/components/resize-panel/resize-panel.tsx index 42584bfc82..33599cb100 100644 --- a/packages/frontend/component/src/components/resize-panel/resize-panel.tsx +++ b/packages/frontend/component/src/components/resize-panel/resize-panel.tsx @@ -2,6 +2,7 @@ import { assertExists } from '@blocksuite/global/utils'; import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; import { forwardRef, useCallback, useEffect, useRef, useState } from 'react'; +import { useTransition } from 'react-transition-state'; import * as styles from './resize-panel.css'; @@ -116,6 +117,7 @@ const ResizeHandle = ({ ); }; +// delay initial animation to avoid flickering function useEnableAnimation() { const [enable, setEnable] = useState(false); useEffect(() => { @@ -126,6 +128,8 @@ function useEnableAnimation() { return enable; } +const animationTimeout = 300; + export const ResizePanel = forwardRef( function ResizePanel( { @@ -150,15 +154,23 @@ export const ResizePanel = forwardRef( ) { const enableAnimation = useEnableAnimation() && _enableAnimation; const safeWidth = Math.min(maxWidth, Math.max(minWidth, width)); + const [{ status }, toggle] = useTransition({ + timeout: animationTimeout, + }); + useEffect(() => { + toggle(open); + }, [open]); return (
    void; } -type ModalAnimationState = 'entering' | 'entered' | 'exiting' | 'exited'; - -function reduceAnimationState( - state: ModalAnimationState, - action: 'open' | 'close' | 'finish' -) { - switch (action) { - case 'open': - return state === 'entered' || state === 'entering' ? state : 'entering'; - case 'close': - return state === 'exited' || state === 'exiting' ? state : 'exiting'; - case 'finish': - return state === 'entering' ? 'entered' : 'exited'; - } -} +const animationTimeout = 120; export const CMDKModal = ({ onOpenChange, open, children, }: React.PropsWithChildren) => { - const [animationState, dispatch] = useReducer(reduceAnimationState, 'exited'); - + const [{ status }, toggle] = useTransition({ + timeout: animationTimeout, + }); useEffect(() => { - dispatch(open ? 'open' : 'close'); - const timeout = setTimeout(() => { - dispatch('finish'); - }, 120); - - return () => { - clearTimeout(timeout); - }; + toggle(open); }, [open]); - return ( - +
    {children} diff --git a/yarn.lock b/yarn.lock index 65178ffb1d..eac8622cee 100644 --- a/yarn.lock +++ b/yarn.lock @@ -269,6 +269,7 @@ __metadata: react-is: "npm:^18.2.0" react-paginate: "npm:^8.2.0" react-router-dom: "npm:^6.22.1" + react-transition-state: "npm:^2.1.1" react-virtuoso: "npm:~4.6.3" rxjs: "npm:^7.8.1" storybook: "npm:^7.6.17" @@ -381,6 +382,7 @@ __metadata: react-error-boundary: "npm:^4.0.12" react-is: "npm:18.2.0" react-router-dom: "npm:^6.22.1" + react-transition-state: "npm:^2.1.1" react-virtuoso: "npm:~4.6.3" rxjs: "npm:^7.8.1" ses: "npm:^1.3.0" @@ -30819,6 +30821,16 @@ __metadata: languageName: node linkType: hard +"react-transition-state@npm:^2.1.1": + version: 2.1.1 + resolution: "react-transition-state@npm:2.1.1" + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + checksum: 10/992f6a44070c74bdcbeae4f6a2a5dd2429ab031e74a942822f9f2bd40b938e0efcdfbc0736f3f1a1003399191de9e5659397e99b4e901600cd03cc639579da54 + languageName: node + linkType: hard + "react-virtuoso@npm:~4.6.3": version: 4.6.3 resolution: "react-virtuoso@npm:4.6.3"