From 7c0cbbbca70e3ddd3280f6a8880013753ca7ae2d Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 28 Apr 2023 13:06:39 -0400 Subject: [PATCH] Stop `` from overwriting classes on re-render (#2457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add raw layout support to Vue playground We can’t use ?raw here because Vite uses that itself for stuff. So here we opt for ?layout=raw instead * Fix Transition for `appear` overwriting classes on re-render * Set initial state just before animating * Remove unused import * Refactor * Capture snapshot of element just after first render With the new `setInitial` call before the animation starts — we don’t see the actual initial render result in this test because the queue has been emptied by the time it ends * Update changelog --- packages/@headlessui-react/CHANGELOG.md | 1 + .../transitions/transition.test.tsx | 14 +++- .../src/components/transitions/transition.tsx | 23 ++++- .../src/test-utils/snapshot.ts | 25 ++++++ packages/playground-vue/src/App.vue | 84 ++++--------------- packages/playground-vue/src/Layout.vue | 79 +++++++++++++++++ 6 files changed, 153 insertions(+), 73 deletions(-) create mode 100644 packages/@headlessui-react/src/test-utils/snapshot.ts create mode 100644 packages/playground-vue/src/Layout.vue diff --git a/packages/@headlessui-react/CHANGELOG.md b/packages/@headlessui-react/CHANGELOG.md index b1217b0..c43fe32 100644 --- a/packages/@headlessui-react/CHANGELOG.md +++ b/packages/@headlessui-react/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Ensure `FocusTrap` is only active when the given `enabled` value is `true` ([#2456](https://github.com/tailwindlabs/headlessui/pull/2456)) +- Stop `` from overwriting classes on re-render ([#2457](https://github.com/tailwindlabs/headlessui/pull/2457)) ## [1.7.14] - 2023-04-12 diff --git a/packages/@headlessui-react/src/components/transitions/transition.test.tsx b/packages/@headlessui-react/src/components/transitions/transition.test.tsx index 471fca4..9ee4642 100644 --- a/packages/@headlessui-react/src/components/transitions/transition.test.tsx +++ b/packages/@headlessui-react/src/components/transitions/transition.test.tsx @@ -5,6 +5,7 @@ import { suppressConsoleLogs } from '../../test-utils/suppress-console-logs' import { Transition } from './transition' import { executeTimeline } from '../../test-utils/execute-timeline' +import { createSnapshot } from '../../test-utils/snapshot' let act = _act as unknown as (fn: () => T) => PromiseLike @@ -426,9 +427,14 @@ describe('Setup API', () => { }) it('should be possible to passthrough the transition classes and immediately apply the enter transitions when appear is set to true', async () => { - let { container } = await act(() => - render( + let container = createSnapshot() + + function Example() { + let ref = container.use() + + return ( { Children ) - ) + } + + await act(() => render()) expect(container).toBeDefined() diff --git a/packages/@headlessui-react/src/components/transitions/transition.tsx b/packages/@headlessui-react/src/components/transitions/transition.tsx index 9925609..416ff23 100644 --- a/packages/@headlessui-react/src/components/transitions/transition.tsx +++ b/packages/@headlessui-react/src/components/transitions/transition.tsx @@ -33,7 +33,6 @@ import { useTransition } from '../../hooks/use-transition' import { useEvent } from '../../hooks/use-event' import { useDisposables } from '../../hooks/use-disposables' import { classNames } from '../../utils/class-names' -import { env } from '../../utils/env' import { useFlags } from '../../hooks/use-flags' type ContainerElement = MutableRefObject @@ -436,7 +435,7 @@ function TransitionChildFn { + if (initial) setInitial(false) + props.beforeEnter?.() + }) + + let beforeLeave = useEvent(() => { + if (initial) setInitial(false) + props.beforeLeave?.() + }) + return ( @@ -551,7 +560,15 @@ function TransitionRootFn, + children: ( + + ), }, theirProps: {}, defaultTag: Fragment, diff --git a/packages/@headlessui-react/src/test-utils/snapshot.ts b/packages/@headlessui-react/src/test-utils/snapshot.ts new file mode 100644 index 0000000..1b1d111 --- /dev/null +++ b/packages/@headlessui-react/src/test-utils/snapshot.ts @@ -0,0 +1,25 @@ +import { MutableRefObject, useLayoutEffect, useRef } from 'react' + +export function createSnapshot() { + let snapshots: HTMLElement[] = [] + + return { + get latest() { + return snapshots.at(-1) + }, + + get firstChild() { + return this.latest?.firstChild ?? null + }, + + use() { + let ref = useRef(null) + useLayoutEffect(() => this.take(ref), []) + return ref + }, + + take(ref: MutableRefObject) { + snapshots.push(ref.current!.parentElement!.cloneNode(true) as any) + }, + } +} diff --git a/packages/playground-vue/src/App.vue b/packages/playground-vue/src/App.vue index 9e6dfa7..d1c457d 100644 --- a/packages/playground-vue/src/App.vue +++ b/packages/playground-vue/src/App.vue @@ -1,81 +1,31 @@ diff --git a/packages/playground-vue/src/Layout.vue b/packages/playground-vue/src/Layout.vue new file mode 100644 index 0000000..29614fa --- /dev/null +++ b/packages/playground-vue/src/Layout.vue @@ -0,0 +1,79 @@ + + +