From ce12406ec2e6df101554c1a8a01680dde55cc2af Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Sat, 28 May 2022 23:28:51 +0200 Subject: [PATCH] fix transition `enter` bug (#1519) We had an issue where an open Dialog got hidden by css didn't properly unmount because the Transition never "finished". We fixed this by checking if the node was hidden by using `getBoundingClientRect`. Today I learned that just *reading* those values (aka call `node.getBoundingClientRect()`) it for whatever reason completely stops the transition. This causes the enter transitions to completely stop working. Instead, we move this code so that we only check the existence of the Node when we try to transition out because this means that the Node is definitely there, just have to check its bounding rect. --- .../src/components/transitions/transition.tsx | 12 +++++++++++- .../@headlessui-react/src/hooks/use-transition.ts | 11 ----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/@headlessui-react/src/components/transitions/transition.tsx b/packages/@headlessui-react/src/components/transitions/transition.tsx index d2c02d8..09fd8f0 100644 --- a/packages/@headlessui-react/src/components/transitions/transition.tsx +++ b/packages/@headlessui-react/src/components/transitions/transition.tsx @@ -339,7 +339,8 @@ let TransitionRoot = forwardRefWithAs(function Transition< >(props: TransitionChildProps & { show?: boolean; appear?: boolean }, ref: Ref) { // @ts-expect-error let { show, appear = false, unmount, ...theirProps } = props as typeof props - let transitionRef = useSyncRefs(ref) + let internalTransitionRef = useRef(null) + let transitionRef = useSyncRefs(internalTransitionRef, ref) // The TransitionChild will also call this hook, and we have to make sure that we are ready. useServerHandoffComplete() @@ -390,6 +391,15 @@ let TransitionRoot = forwardRefWithAs(function Transition< setState(TreeStates.Visible) } else if (!hasChildren(nestingBag)) { setState(TreeStates.Hidden) + } else { + let node = internalTransitionRef.current + if (!node) return + let rect = node.getBoundingClientRect() + + if (rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0) { + // The node is completely hidden, let's hide it + setState(TreeStates.Hidden) + } } }, [show, nestingBag]) diff --git a/packages/@headlessui-react/src/hooks/use-transition.ts b/packages/@headlessui-react/src/hooks/use-transition.ts index dcf04bc..7c1b029 100644 --- a/packages/@headlessui-react/src/hooks/use-transition.ts +++ b/packages/@headlessui-react/src/hooks/use-transition.ts @@ -72,17 +72,6 @@ export function useTransition({ if (latestDirection.current === 'idle') return // We don't need to transition if (!mounted.current) return - dd.add(() => { - if (!node) return - - let rect = node.getBoundingClientRect() - - if (rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0) { - // The node is completely hidden - onStop.current(latestDirection.current) - } - }) - dd.dispose() beforeEvent()