From 343a7da9faea5f6be43842793c160a4933fce723 Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Sun, 23 Aug 2026 11:09:16 +0700 Subject: [PATCH 1/2] fix(appbar): make back icon respect the icon from Provider settings --- src/components/Appbar/AppbarBackIcon.tsx | 7 +- .../__tests__/Appbar/Appbar.test.tsx | 65 ++++++++++++++++++- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/src/components/Appbar/AppbarBackIcon.tsx b/src/components/Appbar/AppbarBackIcon.tsx index ff827b3f5f..3383909603 100644 --- a/src/components/Appbar/AppbarBackIcon.tsx +++ b/src/components/Appbar/AppbarBackIcon.tsx @@ -2,7 +2,7 @@ import { Image, Platform, StyleSheet, View } from 'react-native'; import type { ColorValue } from 'react-native'; import { useLocale } from '../../core/locale'; -import MaterialCommunityIcon from '../MaterialCommunityIcon'; +import Icon from '../Icon'; const AppbarBackIcon = ({ size, @@ -34,11 +34,10 @@ const AppbarBackIcon = ({ /> ) : ( - ); }; diff --git a/src/components/__tests__/Appbar/Appbar.test.tsx b/src/components/__tests__/Appbar/Appbar.test.tsx index 27cd573f9d..481fbdec13 100644 --- a/src/components/__tests__/Appbar/Appbar.test.tsx +++ b/src/components/__tests__/Appbar/Appbar.test.tsx @@ -1,9 +1,10 @@ -import { Animated } from 'react-native'; +import { Animated, Platform, Text as RNText } from 'react-native'; -import { describe, expect, it, jest } from '@jest/globals'; -import { act } from '@testing-library/react-native'; +import { afterEach, describe, expect, it, jest } from '@jest/globals'; +import { act, render as rtlRender } from '@testing-library/react-native'; import { SafeAreaProvider } from 'react-native-safe-area-context'; +import PaperProvider from '../../../core/PaperProvider'; import { getTheme } from '../../../core/theming'; import { render, screen } from '../../../test-utils'; import { tokens } from '../../../theme/tokens'; @@ -14,6 +15,7 @@ import { modeTextVariant, renderAppbarContent as utilRenderAppbarContent, } from '../../Appbar/utils'; +import type { IconProps } from '../../MaterialCommunityIcon'; import Menu from '../../Menu/Menu'; import Searchbar from '../../Searchbar'; import Text from '../../Typography/Text'; @@ -453,3 +455,60 @@ describe('animated value changes correctly', () => { }); }); }); + +describe('Appbar.BackAction icon', () => { + const originalPlatform = Platform.OS; + + afterEach(() => { + Platform.OS = originalPlatform; + }); + + const CustomIcon = ({ name, size, direction, testID }: IconProps) => ( + + {`custom-${name}`} + + ); + + const renderBackAction = (direction?: 'ltr' | 'rtl') => + rtlRender( + + {}} testID="back-action" /> + + ); + + it('renders the icon provided through PaperProvider settings', async () => { + Platform.OS = 'android'; + + await renderBackAction(); + + expect( + screen.getByText('custom-arrow-left', { includeHiddenElements: true }) + ).toBeOnTheScreen(); + }); + + it('keeps the icon mirrored in RTL', async () => { + Platform.OS = 'android'; + + await renderBackAction('rtl'); + + expect( + screen.getByText('custom-arrow-left', { includeHiddenElements: true }) + ).toHaveStyle({ transform: [{ scaleX: -1 }] }); + }); + + it('keeps the icon unmirrored in LTR', async () => { + Platform.OS = 'android'; + + await renderBackAction('ltr'); + + expect( + screen.getByText('custom-arrow-left', { includeHiddenElements: true }) + ).toHaveStyle({ transform: [{ scaleX: 1 }] }); + }); +}); From 62ebaceef6cf5fd52712c6291833a4d14597a155 Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Tue, 25 Aug 2026 09:04:54 +0700 Subject: [PATCH 2/2] fix(appbar): respect the configured icon renderer on iOS Keep the bundled chevron only while the default renderer is in place, so an icon renderer passed through PaperProvider settings is also used for the back icon on iOS. --- src/components/Appbar/AppbarBackIcon.tsx | 12 +++++++++++- src/components/__tests__/Appbar/Appbar.test.tsx | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/components/Appbar/AppbarBackIcon.tsx b/src/components/Appbar/AppbarBackIcon.tsx index 3383909603..41a85a4a81 100644 --- a/src/components/Appbar/AppbarBackIcon.tsx +++ b/src/components/Appbar/AppbarBackIcon.tsx @@ -1,8 +1,12 @@ +import * as React from 'react'; import { Image, Platform, StyleSheet, View } from 'react-native'; import type { ColorValue } from 'react-native'; import { useLocale } from '../../core/locale'; +import { SettingsContext } from '../../core/settings'; +import type { Settings } from '../../core/settings'; import Icon from '../Icon'; +import MaterialCommunityIcon from '../MaterialCommunityIcon'; const AppbarBackIcon = ({ size, @@ -12,10 +16,16 @@ const AppbarBackIcon = ({ color: ColorValue; }) => { const { direction } = useLocale(); + const { icon } = React.useContext(SettingsContext); const isRTL = direction === 'rtl'; const iosIconSize = size - 3; - return Platform.OS === 'ios' ? ( + // The bundled chevron is only kept while the default icon renderer is in + // place, so a renderer configured through `PaperProvider` wins on iOS too. + const shouldUseIOSAsset = + Platform.OS === 'ios' && (!icon || icon === MaterialCommunityIcon); + + return shouldUseIOSAsset ? ( { ).toBeOnTheScreen(); }); + it('renders the icon provided through PaperProvider settings on iOS', async () => { + Platform.OS = 'ios'; + + await renderBackAction(); + + expect( + screen.getByText('custom-arrow-left', { includeHiddenElements: true }) + ).toBeOnTheScreen(); + }); + it('keeps the icon mirrored in RTL', async () => { Platform.OS = 'android';