Skip to content

Commit 990b179

Browse files
authored
Ensure unmount on Dialog works in combination with the transition prop on DialogBackdrop and DialogPanel components (#3352)
* inherit `unmount` from `Dialog` in `DialogBackdrop` and `DialogPanel` components Only the `Dialog` accepts an `unmount` prop because it's the `Dialog` that is conditionally rendered and the `DialogBackdrop` and `DialogPanel` will conditionally show together with the `Dialog`. However, now that the `Dialog` is wrapped in a `Transition` (which can be unmounted) and the `DialogBackdrop` and `DialogPanel` will also be wrapped in a `TransitionChild` (when the `transition` prop is passed) then we do have to deal with the `unmount` state on the `TransitionChild`. This is important because if you make the `Dialog` `unmount={false}`, then the `DialogPanel` will still unmount because the `TransitionChild` is unmounting its children. This now means that you will lose data (such as form state of inputs). This commit solves that by inheriting the `unmount` state of the `Dialog` in the `TransitionChild` wrappers such that they behave the way you expect them to behave. * update changelog
1 parent fbad6a9 commit 990b179

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

packages/@headlessui-react/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111

1212
- Fix prematurely added anchoring styles on `ListboxOptions` ([#3337](https://github.com/tailwindlabs/headlessui/pull/3337))
13+
- Ensure `unmount` on `Dialog` works in combination with the `transition` prop on `DialogBackdrop` and `DialogPanel` components ([#3352](https://github.com/tailwindlabs/headlessui/pull/3352))
1314

1415
## [2.1.1] - 2024-06-26
1516

packages/@headlessui-react/src/components/dialog/dialog.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ let DialogContext = createContext<
8484
| [
8585
{
8686
dialogState: DialogStates
87+
unmount: boolean
8788
close(): void
8889
setTitleId(id: string | null): void
8990
},
@@ -121,6 +122,7 @@ let InternalDialog = forwardRefWithAs(function InternalDialog<
121122
role = 'dialog',
122123
autoFocus = true,
123124
__demoMode = false,
125+
unmount = false,
124126
...theirProps
125127
} = props
126128

@@ -248,8 +250,8 @@ let InternalDialog = forwardRefWithAs(function InternalDialog<
248250
let [describedby, DescriptionProvider] = useDescriptions()
249251

250252
let contextBag = useMemo<ContextType<typeof DialogContext>>(
251-
() => [{ dialogState, close, setTitleId }, state],
252-
[dialogState, state, close, setTitleId]
253+
() => [{ dialogState, close, setTitleId, unmount }, state],
254+
[dialogState, state, close, setTitleId, unmount]
253255
)
254256

255257
let slot = useMemo(
@@ -265,6 +267,7 @@ let InternalDialog = forwardRefWithAs(function InternalDialog<
265267
'aria-modal': __demoMode ? undefined : dialogState === DialogStates.Open ? true : undefined,
266268
'aria-labelledby': state.titleId,
267269
'aria-describedby': describedby,
270+
unmount,
268271
}
269272

270273
let shouldMoveFocusInside = !useIsTouchDevice()
@@ -421,7 +424,7 @@ function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
421424
) {
422425
let internalId = useId()
423426
let { id = `headlessui-dialog-panel-${internalId}`, transition = false, ...theirProps } = props
424-
let [{ dialogState }, state] = useDialogContext('Dialog.Panel')
427+
let [{ dialogState, unmount }, state] = useDialogContext('Dialog.Panel')
425428
let panelRef = useSyncRefs(ref, state.panelRef)
426429

427430
let slot = useMemo(
@@ -442,9 +445,10 @@ function PanelFn<TTag extends ElementType = typeof DEFAULT_PANEL_TAG>(
442445
}
443446

444447
let Wrapper = transition ? TransitionChild : Fragment
448+
let wrapperProps = transition ? { unmount } : {}
445449

446450
return (
447-
<Wrapper>
451+
<Wrapper {...wrapperProps}>
448452
{render({
449453
ourProps,
450454
theirProps,
@@ -475,7 +479,7 @@ function BackdropFn<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG>(
475479
ref: Ref<HTMLElement>
476480
) {
477481
let { transition = false, ...theirProps } = props
478-
let [{ dialogState }] = useDialogContext('Dialog.Backdrop')
482+
let [{ dialogState, unmount }] = useDialogContext('Dialog.Backdrop')
479483

480484
let slot = useMemo(
481485
() => ({ open: dialogState === DialogStates.Open }) satisfies BackdropRenderPropArg,
@@ -485,9 +489,10 @@ function BackdropFn<TTag extends ElementType = typeof DEFAULT_BACKDROP_TAG>(
485489
let ourProps = { ref, 'aria-hidden': true }
486490

487491
let Wrapper = transition ? TransitionChild : Fragment
492+
let wrapperProps = transition ? { unmount } : {}
488493

489494
return (
490-
<Wrapper>
495+
<Wrapper {...wrapperProps}>
491496
{render({
492497
ourProps,
493498
theirProps,

0 commit comments

Comments
 (0)