Fix two issues with Transitions

* TransitionChild's initial state was wrong with unmount=false
* entered classes were not being removed correctly at the start of a transition
This commit is contained in:
Ryan Gossiaux
2021-12-22 11:59:18 -08:00
parent d21287eace
commit 96b165acc0
3 changed files with 30 additions and 11 deletions

View File

@@ -40,16 +40,19 @@
const dispatch = createEventDispatcher(); const dispatch = createEventDispatcher();
let container: HTMLElement | null = null; let container: HTMLElement | null = null;
let state = TreeStates.Visible;
let transitionContext = useTransitionContext(); let transitionContext = useTransitionContext();
let nestingContext = useParentNesting(); let nestingContext = useParentNesting();
let state =
$transitionContext.initialShow || $$props.unmount !== false
? TreeStates.Visible
: TreeStates.Hidden;
let initial = true; let initial = true;
let id = useId(); let id = useId();
let isTransitioning = false; let isTransitioning = false;
$: strategy =
$$props.unmount === false ? RenderStrategy.Hidden : RenderStrategy.Unmount;
let nesting: Writable<NestingContextValues> = writable( let nesting: Writable<NestingContextValues> = writable(
useNesting(() => { useNesting(() => {
@@ -68,7 +71,7 @@
$: { $: {
(() => { (() => {
// If we are in another mode than the Hidden mode then ignore // If we are in another mode than the Hidden mode then ignore
/* if (strategy.value !== RenderStrategy.Hidden) return */ if (strategy !== RenderStrategy.Hidden) return;
if (!id) return; if (!id) return;
// Make sure that we are visible // Make sure that we are visible
@@ -90,13 +93,15 @@
.filter((className) => className.trim().length > 1); .filter((className) => className.trim().length > 1);
} }
let enterClasses = splitClasses(enter); $: enterClasses = splitClasses(enter);
let enterFromClasses = splitClasses(enterFrom); $: enterFromClasses = splitClasses(enterFrom);
let enterToClasses = splitClasses(enterTo); $: enterToClasses = splitClasses(enterTo);
let leaveClasses = splitClasses(leave); $: enteredClasses = splitClasses(entered);
let leaveFromClasses = splitClasses(leaveFrom);
let leaveToClasses = splitClasses(leaveTo); $: leaveClasses = splitClasses(leave);
$: leaveFromClasses = splitClasses(leaveFrom);
$: leaveToClasses = splitClasses(leaveTo);
let mounted = false; let mounted = false;
onMount(() => (mounted = true)); onMount(() => (mounted = true));
@@ -120,6 +125,7 @@
enterClasses, enterClasses,
enterFromClasses, enterFromClasses,
enterToClasses, enterToClasses,
enteredClasses,
(reason) => { (reason) => {
isTransitioning = false; isTransitioning = false;
if (reason === Reason.Finished) dispatch("afterEnter"); if (reason === Reason.Finished) dispatch("afterEnter");
@@ -130,6 +136,7 @@
leaveClasses, leaveClasses,
leaveFromClasses, leaveFromClasses,
leaveToClasses, leaveToClasses,
enteredClasses,
(reason) => { (reason) => {
isTransitioning = false; isTransitioning = false;

View File

@@ -15,6 +15,12 @@
interface TransitionContextValues { interface TransitionContextValues {
show: boolean; show: boolean;
appear: boolean; appear: boolean;
// This is not part of base Headless UI, but we need it because TransitionRoot does not render.
// In base Headless UI, for a component with unmount=false, the initial state for the Child is
// still "visible". It still works, because the parent still is hidden and has display: none
// In our version the parent renders nothing, so we need to send down the correct initial state
// ourselves.
initialShow: boolean;
} }
const TRANSITION_CONTEXT_NAME = "headlessui-transition-context"; const TRANSITION_CONTEXT_NAME = "headlessui-transition-context";
@@ -148,6 +154,9 @@
show, show,
openClosedState !== undefined ? $openClosedState : undefined openClosedState !== undefined ? $openClosedState : undefined
); );
let initialShow = shouldShow;
$: { $: {
shouldShow = computeShow( shouldShow = computeShow(
show, show,
@@ -172,6 +181,7 @@
$: transitionBag.set({ $: transitionBag.set({
show: !!shouldShow, show: !!shouldShow,
appear: appear || !initial, appear: appear || !initial,
initialShow: !!initialShow,
}); });
onMount(() => { onMount(() => {

View File

@@ -62,12 +62,13 @@ export function transition(
base: string[], base: string[],
from: string[], from: string[],
to: string[], to: string[],
entered: string[],
done?: (reason: Reason) => void done?: (reason: Reason) => void
) { ) {
let d = disposables(); let d = disposables();
let _done = done !== undefined ? once(done) : () => { }; let _done = done !== undefined ? once(done) : () => { };
removeClasses(node); removeClasses(node, ...entered);
addClasses(node, ...base, ...from); addClasses(node, ...base, ...from);
d.nextFrame(() => { d.nextFrame(() => {
@@ -77,6 +78,7 @@ export function transition(
d.add( d.add(
waitForTransition(node, (reason) => { waitForTransition(node, (reason) => {
removeClasses(node, ...to, ...base); removeClasses(node, ...to, ...base);
addClasses(node, ...entered);
return _done(reason); return _done(reason);
}) })
); );