From 22de99e2ef0a5d194cdc43bf5d509860b778e8dd Mon Sep 17 00:00:00 2001 From: lukewalczak Date: Fri, 25 Apr 2025 11:33:27 +0200 Subject: [PATCH 1/2] fix: isleading prop behaviour --- src/components/Appbar/Appbar.tsx | 21 ++++++++------------- src/components/Appbar/utils.ts | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/components/Appbar/Appbar.tsx b/src/components/Appbar/Appbar.tsx index e1b251ea9a..663427f647 100644 --- a/src/components/Appbar/Appbar.tsx +++ b/src/components/Appbar/Appbar.tsx @@ -18,6 +18,7 @@ import { getAppbarBackgroundColor, modeAppbarHeight, renderAppbarContent, + filterAppbarActions, } from './utils'; import { useInternalTheme } from '../../core/theming'; import type { MD3Elevation, ThemeProp } from '../../types'; @@ -228,15 +229,6 @@ const Appbar = ({ shouldAddRightSpacing = shouldCenterContent && rightItemsCount === 0; } - const filterAppbarActions = React.useCallback( - (isLeading = false) => - React.Children.toArray(children).filter((child) => - // @ts-expect-error: TypeScript complains about the type of type but it doesn't matter - isLeading ? child.props.isLeading : !child.props.isLeading - ), - [children] - ); - const spacingStyle = isV3 ? styles.v3Spacing : styles.spacing; const insets = { @@ -264,7 +256,11 @@ const Appbar = ({ {shouldAddLeftSpacing ? : null} {(!isV3 || isMode('small') || isMode('center-aligned')) && renderAppbarContent({ - children, + children: [ + // Filter appbar actions - first leading icons, then trailing icons + ...filterAppbarActions(children, true), + ...filterAppbarActions(children), + ], isDark, theme, isV3, @@ -288,7 +284,7 @@ const Appbar = ({ mode, })} {renderAppbarContent({ - children: filterAppbarActions(true), + children: filterAppbarActions(children, true), isDark, isV3, renderOnly: ['Appbar.Action'], @@ -297,7 +293,7 @@ const Appbar = ({ {/* Right side of row container, can contain other AppbarAction if they are not leading icons */} {renderAppbarContent({ - children: filterAppbarActions(false), + children: filterAppbarActions(children), isDark, isV3, renderExcept: [ @@ -310,7 +306,6 @@ const Appbar = ({ })} - {/* Middle of the row, can contain only AppbarContent */} {renderAppbarContent({ children, isDark, diff --git a/src/components/Appbar/utils.ts b/src/components/Appbar/utils.ts index c69cd67a5a..f5780b0c9d 100644 --- a/src/components/Appbar/utils.ts +++ b/src/components/Appbar/utils.ts @@ -113,6 +113,22 @@ export const modeTextVariant = { 'center-aligned': 'titleLarge', } as const; +/** + * Filtruje akcje w Appbarze na podstawie właściwości isLeading. + * @param children - Dzieci komponentu Appbar do przefiltrowania + * @param isLeading - Czy filtrować akcje wiodące (true) czy niewiodące (false). Domyślnie false. + * @returns Przefiltrowana tablica elementów React + */ +export const filterAppbarActions = ( + children: React.ReactNode, + isLeading = false +) => { + return React.Children.toArray(children).filter((child) => { + if (!React.isValidElement(child)) return false; + return isLeading ? child.props.isLeading : !child.props.isLeading; + }); +}; + export const renderAppbarContent = ({ children, isDark, From ae019a0343740ee47ec33e4fd196efd91b01ea04 Mon Sep 17 00:00:00 2001 From: lukewalczak Date: Fri, 25 Apr 2025 12:31:49 +0200 Subject: [PATCH 2/2] fix: icons alignment --- src/components/Appbar/Appbar.tsx | 44 +++++++++++++------ src/components/Appbar/AppbarAction.tsx | 2 +- .../Appbar/__snapshots__/Appbar.test.tsx.snap | 4 +- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/components/Appbar/Appbar.tsx b/src/components/Appbar/Appbar.tsx index 663427f647..231b4a9774 100644 --- a/src/components/Appbar/Appbar.tsx +++ b/src/components/Appbar/Appbar.tsx @@ -211,12 +211,14 @@ const Appbar = ({ React.Children.forEach(children, (child) => { if (React.isValidElement(child)) { + const isLeading = child.props.isLeading === true; + if (child.type === AppbarContent) { hasAppbarContent = true; - } else if (hasAppbarContent) { - rightItemsCount++; - } else { + } else if (isLeading || !hasAppbarContent) { leftItemsCount++; + } else { + rightItemsCount++; } } }); @@ -254,18 +256,32 @@ const Appbar = ({ {...rest} > {shouldAddLeftSpacing ? : null} - {(!isV3 || isMode('small') || isMode('center-aligned')) && - renderAppbarContent({ - children: [ + {(!isV3 || isMode('small') || isMode('center-aligned')) && ( + <> + {/* Render only the back action at first place */} + {renderAppbarContent({ + children, + isDark, + theme, + isV3, + renderOnly: ['Appbar.BackAction'], + shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent, + })} + {/* Render the rest of the content except the back action */} + {renderAppbarContent({ // Filter appbar actions - first leading icons, then trailing icons - ...filterAppbarActions(children, true), - ...filterAppbarActions(children), - ], - isDark, - theme, - isV3, - shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent, - })} + children: [ + ...filterAppbarActions(children, true), + ...filterAppbarActions(children), + ], + isDark, + theme, + isV3, + renderExcept: ['Appbar.BackAction'], + shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent, + })} + + )} {(isMode('medium') || isMode('large')) && ( & { /** * @supported Available in v5.x with theme version 3 * - * Whether it's the leading button. + * Whether it's the leading button. Note: If `Appbar.BackAction` is present, it will be rendered before any `isLeading` icons. */ isLeading?: boolean; style?: Animated.WithAnimatedValue>; diff --git a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap index 9b00150ddf..0eca20beef 100644 --- a/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap +++ b/src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap @@ -652,7 +652,9 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A "paddingHorizontal": 0, }, [ - false, + { + "marginLeft": 12, + }, false, undefined, ],