diff --git a/packages/@headlessui-react/src/components/transitions/transition.test.tsx b/packages/@headlessui-react/src/components/transitions/transition.test.tsx
index 6acb8a57d6..90863b5d53 100644
--- a/packages/@headlessui-react/src/components/transitions/transition.test.tsx
+++ b/packages/@headlessui-react/src/components/transitions/transition.test.tsx
@@ -120,7 +120,9 @@ describe('Setup API', () => {
it('should be possible to use a render prop', () => {
const { container } = render(
- {ref => Children}
+
+ {() => Children}
+
)
expect(container.firstChild).toMatchInlineSnapshot(`
@@ -131,12 +133,20 @@ describe('Setup API', () => {
})
it(
- 'should yell at us when we forget to apply the ref when using a render prop',
+ 'should yell at us when we forget to forward the ref when using a render prop',
suppressConsoleLogs(() => {
expect.assertions(1)
+ function Dummy(props: any) {
+ return Children
+ }
+
expect(() => {
- render({() => Children})
+ render(
+
+ {() => }
+
+ )
}).toThrowErrorMatchingInlineSnapshot(
`"Did you forget to passthrough the \`ref\` to the actual DOM node?"`
)
@@ -253,8 +263,10 @@ describe('Setup API', () => {
const { container } = render(
- {ref => }
- {ref => }
+ {() => }
+
+ {() => }
+
)
@@ -278,11 +290,15 @@ describe('Setup API', () => {
it('should be possible to use render props on the Transition and Transition.Child components', () => {
const { container } = render(
-
- {ref => (
-
- {ref => }
- {ref => }
+
+ {() => (
+
+
+ {() => }
+
+
+ {() => }
+
)}
@@ -306,16 +322,24 @@ describe('Setup API', () => {
})
it(
- 'should yell at us when we forgot to apply the ref on one of the Transition.Child components',
+ 'should yell at us when we forgot to forward the ref on one of the Transition.Child components',
suppressConsoleLogs(() => {
expect.assertions(1)
+ function Dummy(props: any) {
+ return
+ }
+
expect(() => {
render(
- {ref => }
- {() => }
+
+ {() => Sidebar}
+
+
+ {() => Content}
+
)
@@ -326,21 +350,23 @@ describe('Setup API', () => {
)
it(
- 'should yell at us when we forgot to apply a ref on the Transition component',
+ 'should yell at us when we forgot to forward a ref on the Transition component',
suppressConsoleLogs(() => {
expect.assertions(1)
+ function Dummy(props: any) {
+ return
+ }
+
expect(() => {
render(
-
+
{() => (
-
- {ref => }
-
- {ref => }
-
-
+
+ {() => }
+ {() => }
+
)}
diff --git a/packages/@headlessui-react/src/components/transitions/transition.tsx b/packages/@headlessui-react/src/components/transitions/transition.tsx
index 37c035c894..71fde1b8c4 100644
--- a/packages/@headlessui-react/src/components/transitions/transition.tsx
+++ b/packages/@headlessui-react/src/components/transitions/transition.tsx
@@ -1,11 +1,12 @@
import * as React from 'react'
+import { Props } from 'types'
import { useId } from '../../hooks/use-id'
import { useIsInitialRender } from '../../hooks/use-is-initial-render'
import { useIsMounted } from '../../hooks/use-is-mounted'
import { useIsoMorphicEffect } from '../../hooks/use-iso-morphic-effect'
-import { match } from '../../utils/match'
+import { Features, PropsForFeatures, render } from '../../utils/render'
import { Reason, transition } from './utils/transition'
type ID = ReturnType
@@ -43,24 +44,9 @@ export type TransitionEvents = Partial<{
afterLeave(): void
}>
-type HTMLTags = keyof JSX.IntrinsicElements
-type HTMLTagProps = JSX.IntrinsicElements[TTag]
-
-type AsShortcut = {
- children?: React.ReactNode
- as?: TTag
-} & Omit, 'ref'>
-
-type AsRenderPropFunction = {
- children: (ref: React.MutableRefObject) => JSX.Element
-}
-
-type BaseConfig = Partial<{ appear: boolean }>
-
-type TransitionChildProps = BaseConfig &
- (AsShortcut | AsRenderPropFunction) &
- TransitionClasses &
- TransitionEvents
+type TransitionChildProps = Props &
+ PropsForFeatures &
+ Partial<{ appear: boolean } & TransitionClasses & TransitionEvents>
function useTransitionContext() {
const context = React.useContext(TransitionContext)
@@ -156,7 +142,15 @@ function useEvents(events: TransitionEvents) {
return eventsRef
}
-function TransitionChild(props: TransitionChildProps) {
+// ---
+
+const DEFAULT_TRANSITION_CHILD_TAG = 'div'
+type TransitionChildRenderPropArg = React.MutableRefObject
+const TransitionChildRenderFeatures = Features.RenderStrategy
+
+function TransitionChild(
+ props: TransitionChildProps
+) {
const {
// Event "handlers"
beforeEnter,
@@ -171,9 +165,6 @@ function TransitionChild(props: TransitionChildPr
leave,
leaveFrom,
leaveTo,
-
- // ..
- children,
...rest
} = props
const container = React.useRef(null)
@@ -266,32 +257,27 @@ function TransitionChild(props: TransitionChildPr
leaveToClasses,
])
- // Unmount the whole tree
- if (state === TreeStates.Hidden) return null
+ const propsBag = {}
+ const propsWeControl = { ref: container }
+ const passthroughProps = rest
- if (typeof children === 'function') {
- return (
-
- {(children as AsRenderPropFunction['children'])(container)}
-
- )
- }
-
- const { as: Component = 'div', ...passthroughProps } = rest as AsShortcut
return (
- {/* @ts-expect-error Expression produces a union type that is too complex to represent. */}
-
- {children}
-
+ {render(
+ { ...passthroughProps, ...propsWeControl },
+ propsBag,
+ DEFAULT_TRANSITION_CHILD_TAG,
+ TransitionChildRenderFeatures,
+ state === TreeStates.Visible
+ )}
)
}
-export function Transition(
+export function Transition(
props: TransitionChildProps & { show: boolean; appear?: boolean }
) {
- const { show, appear = false, ...rest } = props
+ const { show, appear = false, unmount, ...passthroughProps } = props
if (![true, false].includes(show)) {
throw new Error('A is used but it is missing a `show={true | false}` prop.')
@@ -317,13 +303,22 @@ export function Transition(
}
}, [show, nestingBag])
+ const sharedProps = { unmount }
+
return (
- {match(state, {
- [TreeStates.Visible]: () => ,
- [TreeStates.Hidden]: null,
- })}
+ {render(
+ {
+ ...sharedProps,
+ as: React.Fragment,
+ children: ,
+ },
+ null,
+ React.Fragment,
+ TransitionChildRenderFeatures,
+ state === TreeStates.Visible
+ )}
)