Skip to content

Commit eece348

Browse files
authored
fix: appbar content title container adjustments (#3596)
1 parent 06af55e commit eece348

File tree

3 files changed

+89
-30
lines changed

3 files changed

+89
-30
lines changed

src/components/Appbar/AppbarContent.tsx

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,22 @@ import type { $RemoveChildren, MD3TypescaleKey, ThemeProp } from '../../types';
1818
import Text from '../Typography/Text';
1919
import { modeTextVariant } from './utils';
2020

21+
type TitleString = {
22+
title: string;
23+
titleStyle?: StyleProp<TextStyle>;
24+
};
25+
26+
type TitleElement = { title: React.ReactNode; titleStyle?: never };
27+
2128
export type Props = $RemoveChildren<typeof View> & {
29+
// For `title` and `titleStyle` props their types are duplicated due to the generation of documentation.
30+
// Appropriate type for them are either `TitleString` or `TitleElement`, depends on `title` type.
2231
/**
23-
* Custom color for the text.
24-
*/
25-
color?: string;
26-
/**
27-
* Text for the title.
32+
* Text or component for the title.
2833
*/
2934
title: React.ReactNode;
3035
/**
31-
* Style for the title.
36+
* Style for the title, if `title` is a string.
3237
*/
3338
titleStyle?: StyleProp<TextStyle>;
3439
/**
@@ -49,6 +54,10 @@ export type Props = $RemoveChildren<typeof View> & {
4954
* Function to execute on press.
5055
*/
5156
onPress?: (e: GestureResponderEvent) => void;
57+
/**
58+
* Custom color for the text.
59+
*/
60+
color?: string;
5261
/**
5362
* @internal
5463
*/
@@ -58,7 +67,11 @@ export type Props = $RemoveChildren<typeof View> & {
5867
* @optional
5968
*/
6069
theme?: ThemeProp;
61-
};
70+
/**
71+
* testID to be used on tests.
72+
*/
73+
testID?: string;
74+
} & (TitleString | TitleElement);
6275

6376
/**
6477
* A component used to display a title and optional subtitle in an appbar.
@@ -92,6 +105,7 @@ const AppbarContent = ({
92105
title,
93106
mode = 'small',
94107
theme: themeOverrides,
108+
testID = 'appbar-content',
95109
...rest
96110
}: Props) => {
97111
const theme = useInternalTheme(themeOverrides);
@@ -123,30 +137,36 @@ const AppbarContent = ({
123137
<View
124138
pointerEvents="box-none"
125139
style={[styles.container, isV3 && modeContainerStyles[mode], style]}
140+
testID={testID}
126141
{...rest}
127142
>
128-
<Text
129-
{...(isV3 && { variant })}
130-
ref={titleRef}
131-
style={[
132-
{
133-
color: titleTextColor,
134-
...(isV3
135-
? theme.fonts[variant]
136-
: Platform.OS === 'ios'
137-
? theme.fonts.regular
138-
: theme.fonts.medium),
139-
},
140-
!isV3 && styles.title,
141-
titleStyle,
142-
]}
143-
numberOfLines={1}
144-
accessible
145-
// @ts-ignore Type '"heading"' is not assignable to type ...
146-
accessibilityRole={Platform.OS === 'web' ? 'heading' : 'header'}
147-
>
148-
{title}
149-
</Text>
143+
{typeof title === 'string' ? (
144+
<Text
145+
{...(isV3 && { variant })}
146+
ref={titleRef}
147+
style={[
148+
{
149+
color: titleTextColor,
150+
...(isV3
151+
? theme.fonts[variant]
152+
: Platform.OS === 'ios'
153+
? theme.fonts.regular
154+
: theme.fonts.medium),
155+
},
156+
!isV3 && styles.title,
157+
titleStyle,
158+
]}
159+
numberOfLines={1}
160+
accessible
161+
// @ts-ignore Type '"heading"' is not assignable to type ...
162+
accessibilityRole={Platform.OS === 'web' ? 'heading' : 'header'}
163+
testID={`${testID}-title-text`}
164+
>
165+
{title}
166+
</Text>
167+
) : (
168+
title
169+
)}
150170
{!isV3 && subtitle ? (
151171
<Text
152172
style={[styles.subtitle, { color: subtitleColor }, subtitleStyle]}

src/components/__tests__/Appbar/Appbar.test.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,15 @@ import AppbarAction from '../../Appbar/AppbarAction';
1414
import AppbarBackAction from '../../Appbar/AppbarBackAction';
1515
import AppbarContent from '../../Appbar/AppbarContent';
1616
import AppbarHeader from '../../Appbar/AppbarHeader';
17-
import { getAppbarColor, renderAppbarContent } from '../../Appbar/utils';
17+
import {
18+
getAppbarColor,
19+
modeTextVariant,
20+
renderAppbarContent,
21+
} from '../../Appbar/utils';
1822
import Menu from '../../Menu/Menu';
1923
import Searchbar from '../../Searchbar';
2024
import Tooltip from '../../Tooltip/Tooltip';
25+
import Text from '../../Typography/Text';
2126

2227
jest.mock('react-native-safe-area-context', () => mockSafeAreaContext);
2328

@@ -272,6 +277,38 @@ describe('AppbarAction', () => {
272277
});
273278
});
274279

280+
describe('AppbarContent', () => {
281+
['small', 'medium', 'large', 'center-aligned'].forEach((mode) =>
282+
it(`should render text component with appropriate variant for ${mode} mode`, () => {
283+
const { getByTestId } = render(
284+
<Appbar mode={mode}>
285+
<Appbar.Content title="Title" />
286+
</Appbar>
287+
);
288+
289+
expect(getByTestId('appbar-content-title-text')).toHaveStyle(
290+
getTheme().fonts[modeTextVariant[mode]]
291+
);
292+
})
293+
);
294+
295+
it('should render component passed to title', () => {
296+
const { getByText } = render(
297+
<Appbar>
298+
<Appbar.Content
299+
title={
300+
<Text testID="title" variant="displaySmall">
301+
Title
302+
</Text>
303+
}
304+
/>
305+
</Appbar>
306+
);
307+
308+
expect(getByText('Title')).toBeDefined();
309+
});
310+
});
311+
275312
describe('getAppbarColors', () => {
276313
const elevation = 4;
277314
const customBackground = 'aquamarine';

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
692692
],
693693
]
694694
}
695+
testID="appbar-content"
695696
>
696697
<Text
697698
accessibilityRole="header"
@@ -727,6 +728,7 @@ exports[`Appbar passes additional props to AppbarBackAction, AppbarContent and A
727728
],
728729
]
729730
}
731+
testID="appbar-content-title-text"
730732
>
731733
Examples
732734
</Text>

0 commit comments

Comments
 (0)