Skip to content

Commit a475b09

Browse files
authored
fix: correct list accordion layout (#3856)
1 parent 46d1201 commit a475b09

File tree

4 files changed

+99
-39
lines changed

4 files changed

+99
-39
lines changed

src/components/List/ListAccordion.tsx

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ import * as React from 'react';
22
import {
33
GestureResponderEvent,
44
I18nManager,
5+
NativeSyntheticEvent,
56
StyleProp,
67
StyleSheet,
78
TextStyle,
9+
TextLayoutEventData,
810
View,
911
ViewProps,
1012
ViewStyle,
@@ -16,7 +18,8 @@ import MaterialCommunityIcon from '../MaterialCommunityIcon';
1618
import TouchableRipple from '../TouchableRipple/TouchableRipple';
1719
import Text from '../Typography/Text';
1820
import { ListAccordionGroupContext } from './ListAccordionGroup';
19-
import { getAccordionColors } from './utils';
21+
import type { Style } from './utils';
22+
import { getAccordionColors, getLeftStyles } from './utils';
2023

2124
export type Props = {
2225
/**
@@ -30,7 +33,7 @@ export type Props = {
3033
/**
3134
* Callback which returns a React element to display on the left side.
3235
*/
33-
left?: (props: { color: string }) => React.ReactNode;
36+
left?: (props: { color: string; style: Style }) => React.ReactNode;
3437
/**
3538
* Callback which returns a React element to display on the right side.
3639
*/
@@ -169,6 +172,17 @@ const ListAccordion = ({
169172
const [expanded, setExpanded] = React.useState<boolean>(
170173
expandedProp || false
171174
);
175+
const [alignToTop, setAlignToTop] = React.useState(false);
176+
177+
const onDescriptionTextLayout = (
178+
event: NativeSyntheticEvent<TextLayoutEventData>
179+
) => {
180+
if (!theme.isV3) {
181+
return;
182+
}
183+
const { nativeEvent } = event;
184+
setAlignToTop(nativeEvent.lines.length >= 2);
185+
};
172186

173187
const handlePressAction = (e: GestureResponderEvent) => {
174188
onPress?.(e);
@@ -206,7 +220,7 @@ const ListAccordion = ({
206220
<View>
207221
<View style={{ backgroundColor: theme?.colors?.background }}>
208222
<TouchableRipple
209-
style={[styles.container, style]}
223+
style={[theme.isV3 ? styles.containerV3 : styles.container, style]}
210224
onPress={handlePress}
211225
onLongPress={onLongPress}
212226
delayLongPress={delayLongPress}
@@ -218,13 +232,19 @@ const ListAccordion = ({
218232
theme={theme}
219233
borderless
220234
>
221-
<View style={styles.row} pointerEvents={pointerEvents}>
235+
<View
236+
style={theme.isV3 ? styles.rowV3 : styles.row}
237+
pointerEvents={pointerEvents}
238+
>
222239
{left
223240
? left({
224241
color: isExpanded ? theme.colors?.primary : descriptionColor,
242+
style: getLeftStyles(alignToTop, description, theme.isV3),
225243
})
226244
: null}
227-
<View style={[styles.item, styles.content]}>
245+
<View
246+
style={[theme.isV3 ? styles.itemV3 : styles.item, styles.content]}
247+
>
228248
<Text
229249
selectable={false}
230250
numberOfLines={titleNumberOfLines}
@@ -249,6 +269,7 @@ const ListAccordion = ({
249269
},
250270
descriptionStyle,
251271
]}
272+
onTextLayout={onDescriptionTextLayout}
252273
>
253274
{description}
254275
</Text>
@@ -283,7 +304,10 @@ const ListAccordion = ({
283304
!child.props.right
284305
) {
285306
return React.cloneElement(child as React.ReactElement<any>, {
286-
style: [styles.child, child.props.style],
307+
style: [
308+
theme.isV3 ? styles.childV3 : styles.child,
309+
child.props.style,
310+
],
287311
theme,
288312
});
289313
}
@@ -301,10 +325,18 @@ const styles = StyleSheet.create({
301325
container: {
302326
padding: 8,
303327
},
328+
containerV3: {
329+
paddingVertical: 8,
330+
paddingRight: 24,
331+
},
304332
row: {
305333
flexDirection: 'row',
306334
alignItems: 'center',
307335
},
336+
rowV3: {
337+
flexDirection: 'row',
338+
marginVertical: 6,
339+
},
308340
multiline: {
309341
height: 40,
310342
alignItems: 'center',
@@ -317,11 +349,18 @@ const styles = StyleSheet.create({
317349
fontSize: 14,
318350
},
319351
item: {
320-
margin: 8,
352+
marginVertical: 6,
353+
paddingLeft: 8,
354+
},
355+
itemV3: {
356+
paddingLeft: 16,
321357
},
322358
child: {
323359
paddingLeft: 64,
324360
},
361+
childV3: {
362+
paddingLeft: 40,
363+
},
325364
content: {
326365
flex: 1,
327366
justifyContent: 'center',

src/components/List/ListItem.tsx

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import * as React from 'react';
22
import {
3-
FlexAlignType,
43
GestureResponderEvent,
54
NativeSyntheticEvent,
65
StyleProp,
@@ -17,7 +16,7 @@ import { useInternalTheme } from '../../core/theming';
1716
import type { $RemoveChildren, EllipsizeProp, ThemeProp } from '../../types';
1817
import TouchableRipple from '../TouchableRipple/TouchableRipple';
1918
import Text from '../Typography/Text';
20-
import { getLeftStyles, getRightStyles } from './utils';
19+
import { Style, getLeftStyles, getRightStyles } from './utils';
2120

2221
type Title =
2322
| React.ReactNode
@@ -37,13 +36,6 @@ type Description =
3736
fontSize: number;
3837
}) => React.ReactNode);
3938

40-
interface Style {
41-
marginLeft?: number;
42-
marginRight?: number;
43-
marginVertical?: number;
44-
alignSelf?: FlexAlignType;
45-
}
46-
4739
export type Props = $RemoveChildren<typeof TouchableRipple> & {
4840
/**
4941
* Title text for the list item.

src/components/List/utils.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StyleSheet } from 'react-native';
1+
import { FlexAlignType, StyleSheet } from 'react-native';
22

33
import color from 'color';
44
import type { EllipsizeProp, InternalTheme } from 'src/types';
@@ -12,6 +12,13 @@ type Description =
1212
fontSize: number;
1313
}) => React.ReactNode);
1414

15+
export type Style = {
16+
marginLeft?: number;
17+
marginRight?: number;
18+
marginVertical?: number;
19+
alignSelf?: FlexAlignType;
20+
};
21+
1522
export const getLeftStyles = (
1623
alignToTop: boolean,
1724
description: Description,

0 commit comments

Comments
 (0)