From 9b8269dd7ee0902a730a6b99cd5791dbe7b26060 Mon Sep 17 00:00:00 2001 From: Konstantin Marushchak Date: Mon, 14 Sep 2026 15:53:01 +0200 Subject: [PATCH 1/2] fix(portal): re-provide the reduce motion preference to portal content Re-provide `ReduceMotionContext` in `Portal`, alongside the settings, locale and theme contexts already forwarded across the portal boundary, so portal content stops falling back to the context default of `false`. --- src/components/Portal/Portal.tsx | 10 +++++++--- src/components/__tests__/Portal.test.tsx | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/components/Portal/Portal.tsx b/src/components/Portal/Portal.tsx index 1326026913..633b1c9a05 100644 --- a/src/components/Portal/Portal.tsx +++ b/src/components/Portal/Portal.tsx @@ -8,6 +8,7 @@ import { Provider as SettingsProvider, } from '../../core/settings'; import { ThemeProvider, useInternalTheme } from '../../core/theming'; +import { ReduceMotionContext } from '../../theme/accessibility/ReduceMotionContext'; import type { ThemeProp } from '../../theme/types'; export type Props = { @@ -46,13 +47,16 @@ const Portal = ({ children, theme: themeOverrides }: Props) => { const { direction } = useLocale(); const settings = React.useContext(SettingsContext); const manager = React.useContext(PortalContext); + const reduceMotion = React.useContext(ReduceMotionContext); return ( - - {children} - + + + {children} + + ); diff --git a/src/components/__tests__/Portal.test.tsx b/src/components/__tests__/Portal.test.tsx index 6865d4d159..7e8118a045 100644 --- a/src/components/__tests__/Portal.test.tsx +++ b/src/components/__tests__/Portal.test.tsx @@ -3,8 +3,10 @@ import { Text } from 'react-native'; import { expect, it, jest } from '@jest/globals'; import { LocaleProvider, useLocale } from '../../core/locale'; +import PaperProvider from '../../core/PaperProvider'; import { useInternalTheme } from '../../core/theming'; import { render, screen } from '../../test-utils'; +import { useReduceMotion } from '../../theme/accessibility/ReduceMotionContext'; import Dialog from '../Dialog/Dialog'; import Modal from '../Modal'; import Portal from '../Portal/Portal'; @@ -60,6 +62,22 @@ it('passes local theme overrides and locale to portal content and updates them', expect(screen.queryByText('2 rtl')).not.toBeOnTheScreen(); }); +const PortalReduceMotionContent = () => ( + {`reduce motion: ${useReduceMotion()}`} +); + +it('passes the reduce motion preference to portal content', async () => { + await render( + + + + + + ); + + expect(await screen.findByText('reduce motion: true')).toBeOnTheScreen(); +}); + it('renders portals in source order when mounted in the same commit', async () => { await render( From 37dc9a3545aaf363fa83824fd14b6ff05530714f Mon Sep 17 00:00:00 2001 From: Konstantin Marushchak Date: Mon, 14 Sep 2026 15:55:05 +0200 Subject: [PATCH 2/2] fix(portal): match the key when replacing a queued portal update Compare the key when looking up the queued `mount` to replace, so an update that arrives before the `PortalManager` ref is attached no longer overwrites an unrelated queued portal. --- src/components/Portal/PortalHost.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Portal/PortalHost.tsx b/src/components/Portal/PortalHost.tsx index ecc20b8a72..4238f48947 100644 --- a/src/components/Portal/PortalHost.tsx +++ b/src/components/Portal/PortalHost.tsx @@ -92,7 +92,9 @@ export default class PortalHost extends React.Component { } else { const op: Operation = { type: 'mount', key, children }; const index = this.queue.findIndex( - (o) => o.type === 'mount' || (o.type === 'update' && o.key === key) + (o) => + (o.type === 'mount' && o.key === key) || + (o.type === 'update' && o.key === key) ); if (index > -1) {