From 0fc6fad11d0761632b8da0dd660293ac44851486 Mon Sep 17 00:00:00 2001 From: Hampus Date: Fri, 9 Oct 2026 14:53:08 +0200 Subject: [PATCH] fix(ui): report the shown carousel step so report flows react (#3353) --- .../stepped_carousel/SteppedCarousel.test.tsx | 35 +++++++++++++++++++ .../ui/stepped_carousel/SteppedCarousel.tsx | 9 ++--- 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.test.tsx diff --git a/fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.test.tsx b/fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.test.tsx new file mode 100644 index 000000000..06bb76140 --- /dev/null +++ b/fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.test.tsx @@ -0,0 +1,35 @@ +// @vitest-environment happy-dom +// SPDX-License-Identifier: AGPL-3.0-or-later + +import {SteppedCarousel} from '@app/features/ui/stepped_carousel/SteppedCarousel'; +import {act} from 'react'; +import {createRoot} from 'react-dom/client'; +import {expect, test, vi} from 'vitest'; + +(globalThis as {IS_REACT_ACT_ENVIRONMENT?: boolean}).IS_REACT_ACT_ENVIRONMENT = true; + +test('reports the step whose pane was just shown', () => { + const container = document.createElement('div'); + document.body.append(container); + const root = createRoot(container); + const onStepShown = vi.fn(); + const render = (step: 'loading' | 'ready') => + act(() => { + root.render( + + {step} + , + ); + }); + render('loading'); + expect(onStepShown).toHaveBeenLastCalledWith('loading'); + render('ready'); + expect(onStepShown).toHaveBeenLastCalledWith('ready'); + act(() => root.unmount()); + container.remove(); +}); diff --git a/fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.tsx b/fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.tsx index f1ef32940..6a7b654fd 100644 --- a/fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.tsx +++ b/fluxer_app/src/features/ui/stepped_carousel/SteppedCarousel.tsx @@ -125,7 +125,8 @@ export function SteppedCarousel({ const paneRef = useRef(null); const pendingFocusRequestRef = useRef(0); const handledFocusRequestRef = useRef(0); - const stepShownRef = useRef({step, onStepShown}); + const onStepShownRef = useRef(onStepShown); + const paneStep = step; const measureNode = useCallback((node: HTMLElement) => { const offsetHeight = node.offsetHeight; const scrollHeight = node.scrollHeight; @@ -146,7 +147,7 @@ export function SteppedCarousel({ (node.querySelector(focusableSelector) ?? node).focus({preventScroll: true}); } } - stepShownRef.current.onStepShown?.(stepShownRef.current.step); + onStepShownRef.current?.(paneStep); let observer: ResizeObserver | null = null; if (typeof ResizeObserver !== 'undefined') { observer = new ResizeObserver(() => { @@ -163,13 +164,13 @@ export function SteppedCarousel({ } }; }, - [measureNode], + [measureNode, paneStep], ); useLayoutEffect(() => { pendingFocusRequestRef.current = model.focusRequestId; }, [model.focusRequestId]); useLayoutEffect(() => { - stepShownRef.current = {step, onStepShown}; + onStepShownRef.current = onStepShown; }); return (