From 76ab0aef5fa4615deb1ceb469dcc4ce6b0d84ba0 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 | 64 ++++++++++++++++++- 2 files changed, 66 insertions(+), 5 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 5bba9563f4..6d26e10d8c 100644 --- a/src/components/__tests__/Appbar/Appbar.test.tsx +++ b/src/components/__tests__/Appbar/Appbar.test.tsx @@ -1,6 +1,10 @@ -import { describe, expect, it } from '@jest/globals'; +import { Platform, Text as RNText } from 'react-native'; + +import { afterEach, describe, expect, it } from '@jest/globals'; +import { 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'; @@ -11,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'; @@ -327,3 +332,60 @@ describe('getAppbarBorders', () => { expect(getAppbarBorders({ height: 60, top: 13 })).toEqual({}); }); }); + +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 99c65fda46949bf02b3ad136d3c1e6b5448f48f6 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';