Skip to content

Commit 21fc010

Browse files
authored
fix: isleading prop behaviour (#4699)
* fix: isleading prop behaviour * fix: icons alignment
1 parent 344ef56 commit 21fc010

File tree

4 files changed

+54
-25
lines changed

4 files changed

+54
-25
lines changed

src/components/Appbar/Appbar.tsx

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
getAppbarBackgroundColor,
1919
modeAppbarHeight,
2020
renderAppbarContent,
21+
filterAppbarActions,
2122
} from './utils';
2223
import { useInternalTheme } from '../../core/theming';
2324
import type { MD3Elevation, ThemeProp } from '../../types';
@@ -210,12 +211,14 @@ const Appbar = ({
210211

211212
React.Children.forEach(children, (child) => {
212213
if (React.isValidElement(child)) {
214+
const isLeading = child.props.isLeading === true;
215+
213216
if (child.type === AppbarContent) {
214217
hasAppbarContent = true;
215-
} else if (hasAppbarContent) {
216-
rightItemsCount++;
217-
} else {
218+
} else if (isLeading || !hasAppbarContent) {
218219
leftItemsCount++;
220+
} else {
221+
rightItemsCount++;
219222
}
220223
}
221224
});
@@ -228,15 +231,6 @@ const Appbar = ({
228231
shouldAddRightSpacing = shouldCenterContent && rightItemsCount === 0;
229232
}
230233

231-
const filterAppbarActions = React.useCallback(
232-
(isLeading = false) =>
233-
React.Children.toArray(children).filter((child) =>
234-
// @ts-expect-error: TypeScript complains about the type of type but it doesn't matter
235-
isLeading ? child.props.isLeading : !child.props.isLeading
236-
),
237-
[children]
238-
);
239-
240234
const spacingStyle = isV3 ? styles.v3Spacing : styles.spacing;
241235

242236
const insets = {
@@ -262,14 +256,32 @@ const Appbar = ({
262256
{...rest}
263257
>
264258
{shouldAddLeftSpacing ? <View style={spacingStyle} /> : null}
265-
{(!isV3 || isMode('small') || isMode('center-aligned')) &&
266-
renderAppbarContent({
267-
children,
268-
isDark,
269-
theme,
270-
isV3,
271-
shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent,
272-
})}
259+
{(!isV3 || isMode('small') || isMode('center-aligned')) && (
260+
<>
261+
{/* Render only the back action at first place */}
262+
{renderAppbarContent({
263+
children,
264+
isDark,
265+
theme,
266+
isV3,
267+
renderOnly: ['Appbar.BackAction'],
268+
shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent,
269+
})}
270+
{/* Render the rest of the content except the back action */}
271+
{renderAppbarContent({
272+
// Filter appbar actions - first leading icons, then trailing icons
273+
children: [
274+
...filterAppbarActions(children, true),
275+
...filterAppbarActions(children),
276+
],
277+
isDark,
278+
theme,
279+
isV3,
280+
renderExcept: ['Appbar.BackAction'],
281+
shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent,
282+
})}
283+
</>
284+
)}
273285
{(isMode('medium') || isMode('large')) && (
274286
<View
275287
style={[
@@ -288,7 +300,7 @@ const Appbar = ({
288300
mode,
289301
})}
290302
{renderAppbarContent({
291-
children: filterAppbarActions(true),
303+
children: filterAppbarActions(children, true),
292304
isDark,
293305
isV3,
294306
renderOnly: ['Appbar.Action'],
@@ -297,7 +309,7 @@ const Appbar = ({
297309
{/* Right side of row container, can contain other AppbarAction if they are not leading icons */}
298310
<View style={styles.rightActionControls}>
299311
{renderAppbarContent({
300-
children: filterAppbarActions(false),
312+
children: filterAppbarActions(children),
301313
isDark,
302314
isV3,
303315
renderExcept: [
@@ -310,7 +322,6 @@ const Appbar = ({
310322
})}
311323
</View>
312324
</View>
313-
{/* Middle of the row, can contain only AppbarContent */}
314325
{renderAppbarContent({
315326
children,
316327
isDark,

src/components/Appbar/AppbarAction.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export type Props = React.ComponentPropsWithoutRef<typeof IconButton> & {
4848
/**
4949
* @supported Available in v5.x with theme version 3
5050
*
51-
* Whether it's the leading button.
51+
* Whether it's the leading button. Note: If `Appbar.BackAction` is present, it will be rendered before any `isLeading` icons.
5252
*/
5353
isLeading?: boolean;
5454
style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;

src/components/Appbar/utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,22 @@ export const modeTextVariant = {
113113
'center-aligned': 'titleLarge',
114114
} as const;
115115

116+
/**
117+
* Filtruje akcje w Appbarze na podstawie właściwości isLeading.
118+
* @param children - Dzieci komponentu Appbar do przefiltrowania
119+
* @param isLeading - Czy filtrować akcje wiodące (true) czy niewiodące (false). Domyślnie false.
120+
* @returns Przefiltrowana tablica elementów React
121+
*/
122+
export const filterAppbarActions = (
123+
children: React.ReactNode,
124+
isLeading = false
125+
) => {
126+
return React.Children.toArray(children).filter((child) => {
127+
if (!React.isValidElement(child)) return false;
128+
return isLeading ? child.props.isLeading : !child.props.isLeading;
129+
});
130+
};
131+
116132
export const renderAppbarContent = ({
117133
children,
118134
isDark,

src/components/__tests__/Appbar/__snapshots__/Appbar.test.tsx.snap

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,9 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
652652
"paddingHorizontal": 0,
653653
},
654654
[
655-
false,
655+
{
656+
"marginLeft": 12,
657+
},
656658
false,
657659
undefined,
658660
],

0 commit comments

Comments
 (0)