fix(ui): report the shown carousel step so report flows react (#3353)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-09 14:53:08 +02:00
1 parent eb329f2cd0
commit 0fc6fad11d
2 files changed
+40 -4

No files matched your search

@@ -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(
<SteppedCarousel
step={step}
steps={[step]}
onStepShown={onStepShown}
data-flx="ui.stepped-carousel.test.carousel"
>
<span data-flx="ui.stepped-carousel.test.step">{step}</span>
</SteppedCarousel>,
);
});
render('loading');
expect(onStepShown).toHaveBeenLastCalledWith('loading');
render('ready');
expect(onStepShown).toHaveBeenLastCalledWith('ready');
act(() => root.unmount());
container.remove();
});
@@ -125,7 +125,8 @@ export function SteppedCarousel<Step extends string>({
const paneRef = useRef<HTMLDivElement | null>(null); const paneRef = useRef<HTMLDivElement | null>(null);
const pendingFocusRequestRef = useRef(0); const pendingFocusRequestRef = useRef(0);
const handledFocusRequestRef = useRef(0); const handledFocusRequestRef = useRef(0);
const stepShownRef = useRef({step, onStepShown}); const onStepShownRef = useRef(onStepShown);
const paneStep = step;
const measureNode = useCallback((node: HTMLElement) => { const measureNode = useCallback((node: HTMLElement) => {
const offsetHeight = node.offsetHeight; const offsetHeight = node.offsetHeight;
const scrollHeight = node.scrollHeight; const scrollHeight = node.scrollHeight;
@@ -146,7 +147,7 @@ export function SteppedCarousel<Step extends string>({
(node.querySelector<HTMLElement>(focusableSelector) ?? node).focus({preventScroll: true}); (node.querySelector<HTMLElement>(focusableSelector) ?? node).focus({preventScroll: true});
} }
} }
stepShownRef.current.onStepShown?.(stepShownRef.current.step); onStepShownRef.current?.(paneStep);
let observer: ResizeObserver | null = null; let observer: ResizeObserver | null = null;
if (typeof ResizeObserver !== 'undefined') { if (typeof ResizeObserver !== 'undefined') {
observer = new ResizeObserver(() => { observer = new ResizeObserver(() => {
@@ -163,13 +164,13 @@ export function SteppedCarousel<Step extends string>({
} }
}; };
}, },
[measureNode], [measureNode, paneStep],
); );
useLayoutEffect(() => { useLayoutEffect(() => {
pendingFocusRequestRef.current = model.focusRequestId; pendingFocusRequestRef.current = model.focusRequestId;
}, [model.focusRequestId]); }, [model.focusRequestId]);
useLayoutEffect(() => { useLayoutEffect(() => {
stepShownRef.current = {step, onStepShown}; onStepShownRef.current = onStepShown;
}); });
return ( return (
<motion.div <motion.div