Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 34 additions & 23 deletions src/components/Appbar/Appbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
getAppbarBackgroundColor,
modeAppbarHeight,
renderAppbarContent,
filterAppbarActions,
} from './utils';
import { useInternalTheme } from '../../core/theming';
import type { MD3Elevation, ThemeProp } from '../../types';
Expand Down Expand Up @@ -210,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++;
}
}
});
Expand All @@ -228,15 +231,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 = {
Expand All @@ -262,14 +256,32 @@ const Appbar = ({
{...rest}
>
{shouldAddLeftSpacing ? <View style={spacingStyle} /> : null}
{(!isV3 || isMode('small') || isMode('center-aligned')) &&
renderAppbarContent({
children,
isDark,
theme,
isV3,
shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent,
})}
{(!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
children: [
...filterAppbarActions(children, true),
...filterAppbarActions(children),
],
isDark,
theme,
isV3,
renderExcept: ['Appbar.BackAction'],
shouldCenterContent: isV3CenterAlignedMode || shouldCenterContent,
})}
</>
)}
{(isMode('medium') || isMode('large')) && (
<View
style={[
Expand All @@ -288,7 +300,7 @@ const Appbar = ({
mode,
})}
{renderAppbarContent({
children: filterAppbarActions(true),
children: filterAppbarActions(children, true),
isDark,
isV3,
renderOnly: ['Appbar.Action'],
Expand All @@ -297,7 +309,7 @@ const Appbar = ({
{/* Right side of row container, can contain other AppbarAction if they are not leading icons */}
<View style={styles.rightActionControls}>
{renderAppbarContent({
children: filterAppbarActions(false),
children: filterAppbarActions(children),
isDark,
isV3,
renderExcept: [
Expand All @@ -310,7 +322,6 @@ const Appbar = ({
})}
</View>
</View>
{/* Middle of the row, can contain only AppbarContent */}
{renderAppbarContent({
children,
isDark,
Expand Down
2 changes: 1 addition & 1 deletion src/components/Appbar/AppbarAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export type Props = React.ComponentPropsWithoutRef<typeof IconButton> & {
/**
* @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<StyleProp<ViewStyle>>;
Expand Down
16 changes: 16 additions & 0 deletions src/components/Appbar/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,9 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
"paddingHorizontal": 0,
},
[
false,
{
"marginLeft": 12,
},
false,
undefined,
],
Expand Down
Loading