소스 검색

Improve disclosure collapse animation

Zack Rauen 1 년 전
부모
커밋
2d1aed4252
2개의 변경된 파일33개의 추가작업 그리고 18개의 파일을 삭제
  1. 16 9
      src/components/bookmarks/group.jsx
  2. 17 9
      src/components/services/group.jsx

+ 16 - 9
src/components/bookmarks/group.jsx

@@ -1,3 +1,4 @@
+import { useRef } from "react";
 import classNames from "classnames";
 import classNames from "classnames";
 import { Disclosure, Transition } from '@headlessui/react';
 import { Disclosure, Transition } from '@headlessui/react';
 import { MdKeyboardArrowDown } from "react-icons/md";
 import { MdKeyboardArrowDown } from "react-icons/md";
@@ -6,6 +7,7 @@ import ErrorBoundary from "components/errorboundry";
 import List from "components/bookmarks/list";
 import List from "components/bookmarks/list";
 
 
 export default function BookmarksGroup({ group, disableCollapse }) {
 export default function BookmarksGroup({ group, disableCollapse }) {
+  const panel = useRef();
   return (
   return (
     <div key={group.name} className="flex-1">
     <div key={group.name} className="flex-1">
     <Disclosure defaultOpen>
     <Disclosure defaultOpen>
@@ -15,19 +17,24 @@ export default function BookmarksGroup({ group, disableCollapse }) {
           <h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
           <h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
           <MdKeyboardArrowDown className={classNames(
           <MdKeyboardArrowDown className={classNames(
             disableCollapse ? 'hidden' : '',
             disableCollapse ? 'hidden' : '',
-            'transition-opacity opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
-            open ? 'rotate-180 transform' : ''
+            'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
+            open ? '' : 'rotate-90'
             )} />
             )} />
         </Disclosure.Button>
         </Disclosure.Button>
         <Transition
         <Transition
-          enter="transition duration-200 ease-out"
-          enterFrom="transform scale-75 opacity-0"
-          enterTo="transform scale-100 opacity-100"
-          leave="transition duration-75 ease-out"
-          leaveFrom="transform scale-100 opacity-100"
-          leaveTo="transform scale-75 opacity-0"
+          // Otherwise the transition group does display: none and cancels animation
+          className="!block"
+          unmount={false}
+          beforeLeave={() => {
+            panel.current.style.height = `${panel.current.scrollHeight}px`;
+            setTimeout(() => {panel.current.style.height = `0`}, 1);
+          }}
+          beforeEnter={() => {
+            panel.current.style.height = `0px`;
+            setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1);
+          }}
           >
           >
-            <Disclosure.Panel>
+            <Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
               <ErrorBoundary>
               <ErrorBoundary>
                 <List bookmarks={group.bookmarks} />
                 <List bookmarks={group.bookmarks} />
               </ErrorBoundary>
               </ErrorBoundary>

+ 17 - 9
src/components/services/group.jsx

@@ -1,3 +1,4 @@
+import { useRef } from "react";
 import classNames from "classnames";
 import classNames from "classnames";
 import { Disclosure, Transition } from '@headlessui/react';
 import { Disclosure, Transition } from '@headlessui/react';
 import { MdKeyboardArrowDown } from "react-icons/md";
 import { MdKeyboardArrowDown } from "react-icons/md";
@@ -7,6 +8,8 @@ import ResolvedIcon from "components/resolvedicon";
 
 
 export default function ServicesGroup({ group, services, layout, fiveColumns, disableCollapse }) {
 export default function ServicesGroup({ group, services, layout, fiveColumns, disableCollapse }) {
 
 
+  const panel = useRef();
+
   return (
   return (
     <div
     <div
       key={services.name}
       key={services.name}
@@ -28,19 +31,24 @@ export default function ServicesGroup({ group, services, layout, fiveColumns, di
           <h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
           <h2 className="flex text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
           <MdKeyboardArrowDown className={classNames(
           <MdKeyboardArrowDown className={classNames(
             disableCollapse ? 'hidden' : '',
             disableCollapse ? 'hidden' : '',
-            'transition-opacity opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
-            open ? 'rotate-180 transform' : ''
+            'transition-all opacity-0 group-hover:opacity-100 ml-auto text-theme-800 dark:text-theme-300 text-xl',
+            open ? '' : 'rotate-90'
             )} />
             )} />
         </Disclosure.Button>
         </Disclosure.Button>
         <Transition
         <Transition
-          enter="transition duration-200 ease-out"
-          enterFrom="transform scale-75 opacity-0"
-          enterTo="transform scale-100 opacity-100"
-          leave="transition duration-75 ease-out"
-          leaveFrom="transform scale-100 opacity-100"
-          leaveTo="transform scale-75 opacity-0"
+          // Otherwise the transition group does display: none and cancels animation
+          className="!block"
+          unmount={false}
+          beforeLeave={() => {
+            panel.current.style.height = `${panel.current.scrollHeight}px`;
+            setTimeout(() => {panel.current.style.height = `0`}, 1);
+          }}
+          beforeEnter={() => {
+            panel.current.style.height = `0px`;
+            setTimeout(() => {panel.current.style.height = `${panel.current.scrollHeight}px`}, 1);
+          }}
           >
           >
-            <Disclosure.Panel>
+            <Disclosure.Panel className="transition-all overflow-hidden duration-300 ease-out" ref={panel} static>
               <List group={group} services={services.services} layout={layout} />
               <List group={group} services={services.services} layout={layout} />
             </Disclosure.Panel>
             </Disclosure.Panel>
         </Transition>
         </Transition>