From 7b6b3019dfaa41e34970e5827bd2ba21c7712fbe Mon Sep 17 00:00:00 2001 From: rahim Date: Thu, 5 Mar 2026 23:51:14 -0800 Subject: [PATCH] fix(core): use double-RAF in transition open to enable entry animations (#755) --- packages/core/src/dom/ui/tests/transition.test.ts | 2 +- packages/core/src/dom/ui/transition.ts | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/core/src/dom/ui/tests/transition.test.ts b/packages/core/src/dom/ui/tests/transition.test.ts index 2bc64395..7d8c30a8 100644 --- a/packages/core/src/dom/ui/tests/transition.test.ts +++ b/packages/core/src/dom/ui/tests/transition.test.ts @@ -16,7 +16,7 @@ describe('createTransition', () => { expect(handler.state.current).toEqual({ active: true, status: 'starting' }); }); - it('transitions to idle after one RAF', async () => { + it('transitions to idle after a double-RAF', async () => { const handler = createTransition(); const promise = handler.open(); diff --git a/packages/core/src/dom/ui/transition.ts b/packages/core/src/dom/ui/transition.ts index 0e47f772..242c62f9 100644 --- a/packages/core/src/dom/ui/transition.ts +++ b/packages/core/src/dom/ui/transition.ts @@ -13,9 +13,9 @@ export interface TransitionApi { /** * Manages open/close transition lifecycle via `createState`. * - * **Open:** patches `{ active: true, status: 'starting' }`, then after one - * RAF patches `{ status: 'idle' }` so the browser paints the initial - * state before transitioning. + * **Open:** patches `{ active: true, status: 'starting' }`, then after a + * double-RAF patches `{ status: 'idle' }` so the browser paints the + * initial ("from") state before transitioning. * * **Close:** patches `{ status: 'ending' }` (keeping `active: true` so the * element stays mounted), then after a double-RAF waits for @@ -39,9 +39,12 @@ export function createTransition(): TransitionApi { return new Promise((resolve) => { rafId1 = requestAnimationFrame(() => { rafId1 = 0; - if (destroyed || !state.current.active) return resolve(); - state.patch({ status: 'idle' }); - resolve(); + rafId2 = requestAnimationFrame(() => { + rafId2 = 0; + if (destroyed || !state.current.active) return resolve(); + state.patch({ status: 'idle' }); + resolve(); + }); }); }); }