[FIX] Wrong styling on E2E encryption banner (#2767)

* [FIX] Wrong styling on E2E encryption banner

* [FIX] Wrong styling on E2E encryption banner

* [FIX] Wrong styling on E2E encryption banner

* [FIX] Wrong styling on E2E encryption banner (#2767)

* Updated SortDropdown, ListHeader, ListItem and added stories for List.Item

* Updated SortDropdown

* Removed unused component

* Updated List.Item and stories

* Reverted unnecessary changes and updated ListItem stories

* Fix minor indentation

* Stop breaking Touch's default underlay color

* Fix indentation

* Remove falsy comparison from render

* Fix left icon

* Use List.Item on OmnichannelStatus

* Add missing separator

* Lint

* Fix sort dropdown

* Remove unnecessary styles

* Fix detox

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Gerzon Z 2021-01-21 15:52:26 -04:00 committed by GitHub
parent 0fdb8f2e46
commit bd09cd32a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 225 additions and 344 deletions

View File

@ -6796,7 +6796,7 @@ exports[`Storyshots List with black theme 1`] = `
</RNCSafeAreaView> </RNCSafeAreaView>
`; `;
exports[`Storyshots List with custom color 1`] = ` exports[`Storyshots List with custom colors 1`] = `
<RCTScrollView <RCTScrollView
contentContainerStyle={ contentContainerStyle={
Object { Object {
@ -6893,6 +6893,65 @@ exports[`Storyshots List with custom color 1`] = `
] ]
} }
/> />
<View
style={
Array [
Object {
"alignItems": "center",
"flex": 1,
"flexDirection": "row",
"justifyContent": "center",
"paddingHorizontal": 12,
},
false,
Object {
"height": 92,
},
]
}
>
<View
style={
Object {
"flex": 1,
"justifyContent": "center",
}
}
>
<Text
numberOfLines={1}
style={
Array [
Object {
"backgroundColor": "transparent",
"fontFamily": "System",
"fontSize": 16,
"fontWeight": "400",
"textAlign": "left",
},
Object {
"color": "white",
},
]
}
>
Press me!
</Text>
</View>
</View>
<View
style={
Array [
Object {
"height": 0.5,
},
undefined,
Object {
"backgroundColor": "#cbcbcc",
},
]
}
/>
</View> </View>
</RCTScrollView> </RCTScrollView>
`; `;

View File

@ -35,6 +35,7 @@ export const themes = {
auxiliaryText: '#9ca2a8', auxiliaryText: '#9ca2a8',
infoText: '#6d6d72', infoText: '#6d6d72',
tintColor: '#1d74f5', tintColor: '#1d74f5',
tintActive: '#549df9',
auxiliaryTintColor: '#6C727A', auxiliaryTintColor: '#6C727A',
actionTintColor: '#1d74f5', actionTintColor: '#1d74f5',
separatorColor: '#cbcbcc', separatorColor: '#cbcbcc',
@ -80,6 +81,7 @@ export const themes = {
auxiliaryText: '#9297a2', auxiliaryText: '#9297a2',
infoText: '#6D6D72', infoText: '#6D6D72',
tintColor: '#1d74f5', tintColor: '#1d74f5',
tintActive: '#549df9',
auxiliaryTintColor: '#f9f9f9', auxiliaryTintColor: '#f9f9f9',
actionTintColor: '#1d74f5', actionTintColor: '#1d74f5',
separatorColor: '#2b2b2d', separatorColor: '#2b2b2d',
@ -125,6 +127,7 @@ export const themes = {
auxiliaryText: '#b2b8c6', auxiliaryText: '#b2b8c6',
infoText: '#6d6d72', infoText: '#6d6d72',
tintColor: '#1e9bfe', tintColor: '#1e9bfe',
tintActive: '#76b7fc',
auxiliaryTintColor: '#f9f9f9', auxiliaryTintColor: '#f9f9f9',
actionTintColor: '#1e9bfe', actionTintColor: '#1e9bfe',
separatorColor: '#272728', separatorColor: '#272728',

View File

@ -1,9 +1,6 @@
import React from 'react'; import React from 'react';
import { import {
View, View, Text, StyleSheet, I18nManager
Text,
StyleSheet,
I18nManager
} from 'react-native'; } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
@ -82,11 +79,12 @@ const Content = React.memo(({
)); ));
const Button = React.memo(({ const Button = React.memo(({
onPress, ...props onPress, backgroundColor, underlayColor, ...props
}) => ( }) => (
<Touch <Touch
onPress={() => onPress(props.title)} onPress={() => onPress(props.title)}
style={{ backgroundColor: themes[props.theme].backgroundColor }} style={{ backgroundColor: backgroundColor || themes[props.theme].backgroundColor }}
underlayColor={underlayColor}
enabled={!props.disabled} enabled={!props.disabled}
theme={props.theme} theme={props.theme}
> >
@ -99,7 +97,7 @@ const ListItem = React.memo(({ ...props }) => {
return <Button {...props} />; return <Button {...props} />;
} }
return ( return (
<View style={{ backgroundColor: themes[props.theme].backgroundColor }}> <View style={{ backgroundColor: props.backgroundColor || themes[props.theme].backgroundColor }}>
<Content {...props} /> <Content {...props} />
</View> </View>
); );
@ -107,7 +105,8 @@ const ListItem = React.memo(({ ...props }) => {
ListItem.propTypes = { ListItem.propTypes = {
onPress: PropTypes.func, onPress: PropTypes.func,
theme: PropTypes.string theme: PropTypes.string,
backgroundColor: PropTypes.string
}; };
ListItem.displayName = 'List.Item'; ListItem.displayName = 'List.Item';
@ -137,7 +136,9 @@ Button.propTypes = {
title: PropTypes.string, title: PropTypes.string,
onPress: PropTypes.func, onPress: PropTypes.func,
disabled: PropTypes.bool, disabled: PropTypes.bool,
theme: PropTypes.string theme: PropTypes.string,
backgroundColor: PropTypes.string,
underlayColor: PropTypes.string
}; };
Button.defaultProps = { Button.defaultProps = {

View File

@ -1,12 +1,8 @@
import React, { memo, useState, useEffect } from 'react'; import React, { memo, useState, useEffect } from 'react';
import { import { View, Switch } from 'react-native';
View, Text, StyleSheet, Switch
} from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Touch from '../../../utils/touch'; import * as List from '../../../containers/List';
import { CustomIcon } from '../../../lib/Icons';
import I18n from '../../../i18n';
import styles from '../../../views/RoomsListView/styles'; import styles from '../../../views/RoomsListView/styles';
import { themes, SWITCH_TRACK_COLOR } from '../../../constants/colors'; import { themes, SWITCH_TRACK_COLOR } from '../../../constants/colors';
import { withTheme } from '../../../theme'; import { withTheme } from '../../../theme';
@ -36,35 +32,32 @@ const OmnichannelStatus = memo(({
}; };
return ( return (
<Touch <>
onPress={goQueue} <List.Item
theme={theme} title='Omnichannel'
style={{ backgroundColor: themes[theme].headerSecondaryBackground }} left={() => <List.Icon name='omnichannel' />}
> color={themes[theme].auxiliaryText}
<View onPress={goQueue}
style={[ right={() => (
styles.dropdownContainerHeader, <View style={styles.omnichannelRightContainer}>
{ borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor } {inquiryEnabled
]} ? (
> <UnreadBadge
<CustomIcon style={[styles.queueIcon, { color: themes[theme].auxiliaryText }]} size={22} name='omnichannel' /> style={styles.queueIcon}
<Text style={[styles.queueToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Omnichannel')}</Text> unread={queueSize}
{inquiryEnabled />
? ( )
<UnreadBadge : null}
style={styles.queueIcon} <Switch
unread={queueSize} value={status}
trackColor={SWITCH_TRACK_COLOR}
onValueChange={toggleLivechat}
/> />
) </View>
: null} )}
<Switch />
style={styles.omnichannelToggle} <List.Separator />
value={status} </>
trackColor={SWITCH_TRACK_COLOR}
onValueChange={toggleLivechat}
/>
</View>
</Touch>
); );
}); });

View File

@ -15,7 +15,7 @@ class Touch extends React.Component {
render() { render() {
const { const {
children, onPress, theme, ...props children, onPress, theme, underlayColor, ...props
} = this.props; } = this.props;
return ( return (
@ -23,7 +23,7 @@ class Touch extends React.Component {
ref={this.getRef} ref={this.getRef}
onPress={onPress} onPress={onPress}
activeOpacity={1} activeOpacity={1}
underlayColor={themes[theme].bannerBackground} underlayColor={underlayColor || themes[theme].bannerBackground}
rippleColor={themes[theme].bannerBackground} rippleColor={themes[theme].bannerBackground}
{...props} {...props}
> >
@ -36,7 +36,8 @@ class Touch extends React.Component {
Touch.propTypes = { Touch.propTypes = {
children: PropTypes.node, children: PropTypes.node,
onPress: PropTypes.func, onPress: PropTypes.func,
theme: PropTypes.string theme: PropTypes.string,
underlayColor: PropTypes.string
}; };
export default Touch; export default Touch;

View File

@ -1,49 +0,0 @@
import React from 'react';
import { Text } from 'react-native';
import PropTypes from 'prop-types';
import { BorderlessButton } from 'react-native-gesture-handler';
import { withTheme } from '../../../theme';
import { CustomIcon } from '../../../lib/Icons';
import { themes } from '../../../constants/colors';
import I18n from '../../../i18n';
import styles from '../styles';
import { E2E_BANNER_TYPE } from '../../../lib/encryption/constants';
const Encryption = React.memo(({
searching,
goEncryption,
encryptionBanner,
theme
}) => {
if (searching > 0 || !encryptionBanner) {
return null;
}
let text = I18n.t('Save_Your_Encryption_Password');
if (encryptionBanner === E2E_BANNER_TYPE.REQUEST_PASSWORD) {
text = I18n.t('Enter_Your_E2E_Password');
}
return (
<BorderlessButton
style={[styles.encryptionButton, { backgroundColor: themes[theme].actionTintColor }]}
theme={theme}
onPress={goEncryption}
testID='listheader-encryption'
accessibilityLabel={text}
>
<CustomIcon name='encrypted' size={24} color={themes[theme].buttonText} style={styles.encryptionIcon} />
<Text style={[styles.encryptionText, { color: themes[theme].buttonText }]}>{text}</Text>
</BorderlessButton>
);
});
Encryption.propTypes = {
searching: PropTypes.bool,
goEncryption: PropTypes.func,
encryptionBanner: PropTypes.string,
theme: PropTypes.string
};
export default withTheme(Encryption);

View File

@ -1,45 +0,0 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import Touch from '../../../utils/touch';
import { CustomIcon } from '../../../lib/Icons';
import I18n from '../../../i18n';
import styles from '../styles';
import { themes } from '../../../constants/colors';
import { withTheme } from '../../../theme';
const Sort = React.memo(({
searching, sortBy, toggleSort, theme
}) => {
if (searching > 0) {
return null;
}
return (
<Touch
onPress={toggleSort}
theme={theme}
style={{ backgroundColor: themes[theme].headerSecondaryBackground }}
>
<View
style={[
styles.dropdownContainerHeader,
{ borderBottomWidth: StyleSheet.hairlineWidth, borderColor: themes[theme].separatorColor }
]}
>
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort' />
<Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text>
</View>
</Touch>
);
});
Sort.propTypes = {
searching: PropTypes.bool,
sortBy: PropTypes.string,
theme: PropTypes.string,
toggleSort: PropTypes.func
};
export default withTheme(Sort);

View File

@ -1,8 +1,11 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Sort from './Sort'; import { withTheme } from '../../../theme';
import Encryption from './Encryption'; import I18n from '../../../i18n';
import * as List from '../../../containers/List';
import { E2E_BANNER_TYPE } from '../../../lib/encryption/constants';
import { themes } from '../../../constants/colors';
import OmnichannelStatus from '../../../ee/omnichannel/containers/OmnichannelStatus'; import OmnichannelStatus from '../../../ee/omnichannel/containers/OmnichannelStatus';
@ -15,14 +18,55 @@ const ListHeader = React.memo(({
queueSize, queueSize,
inquiryEnabled, inquiryEnabled,
encryptionBanner, encryptionBanner,
user user,
}) => ( theme
<> }) => {
<Encryption searching={searching} goEncryption={goEncryption} encryptionBanner={encryptionBanner} /> const sortTitle = I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') });
<Sort searching={searching} sortBy={sortBy} toggleSort={toggleSort} />
<OmnichannelStatus searching={searching} goQueue={goQueue} inquiryEnabled={inquiryEnabled} queueSize={queueSize} user={user} /> if (searching) {
</> return null;
)); }
return (
<>
{encryptionBanner
? (
<>
<List.Item
title={
encryptionBanner === E2E_BANNER_TYPE.REQUEST_PASSWORD
? 'Enter_Your_E2E_Password'
: 'Save_Your_Encryption_Password'
}
left={() => <List.Icon name='encrypted' color={themes[theme].buttonText} />}
underlayColor={themes[theme].tintActive}
backgroundColor={themes[theme].actionTintColor}
color={themes[theme].buttonText}
onPress={goEncryption}
testID='listheader-encryption'
/>
<List.Separator />
</>
)
: null}
<List.Item
title={sortTitle}
left={() => <List.Icon name='sort' />}
color={themes[theme].auxiliaryText}
onPress={toggleSort}
translateTitle={false}
/>
<List.Separator />
<OmnichannelStatus
searching={searching}
goQueue={goQueue}
inquiryEnabled={inquiryEnabled}
queueSize={queueSize}
user={user}
/>
</>
);
});
ListHeader.propTypes = { ListHeader.propTypes = {
searching: PropTypes.bool, searching: PropTypes.bool,
@ -33,7 +77,8 @@ ListHeader.propTypes = {
queueSize: PropTypes.number, queueSize: PropTypes.number,
inquiryEnabled: PropTypes.bool, inquiryEnabled: PropTypes.bool,
encryptionBanner: PropTypes.string, encryptionBanner: PropTypes.string,
user: PropTypes.object user: PropTypes.object,
theme: PropTypes.string
}; };
export default ListHeader; export default withTheme(ListHeader);

View File

@ -1,46 +0,0 @@
import React from 'react';
import { View, Text, Image } from 'react-native';
import PropTypes from 'prop-types';
import styles from '../styles';
import Touch from '../../../utils/touch';
import I18n from '../../../i18n';
import { CustomIcon } from '../../../lib/Icons';
import Check from '../../../containers/Check';
import { themes } from '../../../constants/colors';
export const SortItemButton = ({ children, onPress, theme }) => (
<Touch
style={styles.sortItemButton}
onPress={onPress}
theme={theme}
>
{children}
</Touch>
);
SortItemButton.propTypes = {
theme: PropTypes.string,
children: PropTypes.node,
onPress: PropTypes.func
};
export const SortItemContent = ({
label, icon, imageUri, checked, theme
}) => (
<View style={styles.sortItemContainer}>
{icon && <CustomIcon style={[styles.sortIcon, { color: themes[theme].controlText }]} size={22} name={icon} />}
{imageUri && <Image style={[styles.sortIcon, { tintColor: themes[theme].controlText }]} source={{ uri: imageUri }} />}
<Text style={[styles.sortItemText, { color: themes[theme].controlText }]}>{I18n.t(label)}</Text>
{checked ? <Check theme={theme} /> : null}
</View>
);
SortItemContent.propTypes = {
theme: PropTypes.string,
label: PropTypes.string,
icon: PropTypes.string,
imageUri: PropTypes.string,
checked: PropTypes.bool
};

View File

@ -1,21 +1,19 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { import {
View, Text, Animated, Easing, TouchableWithoutFeedback Animated, Easing, TouchableWithoutFeedback
} from 'react-native'; } from 'react-native';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withSafeAreaInsets } from 'react-native-safe-area-context'; import { withSafeAreaInsets } from 'react-native-safe-area-context';
import styles from '../styles'; import styles from '../styles';
import Touch from '../../../utils/touch'; import * as List from '../../../containers/List';
import RocketChat from '../../../lib/rocketchat'; import RocketChat from '../../../lib/rocketchat';
import { setPreference } from '../../../actions/sortPreferences'; import { setPreference } from '../../../actions/sortPreferences';
import log, { logEvent, events } from '../../../utils/log'; import log, { logEvent, events } from '../../../utils/log';
import I18n from '../../../i18n'; import I18n from '../../../i18n';
import { CustomIcon } from '../../../lib/Icons';
import { withTheme } from '../../../theme'; import { withTheme } from '../../../theme';
import { themes } from '../../../constants/colors'; import { themes } from '../../../constants/colors';
import { SortItemButton, SortItemContent } from './Item';
import { headerHeight } from '../../../containers/Header'; import { headerHeight } from '../../../containers/Header';
const ANIMATION_DURATION = 200; const ANIMATION_DURATION = 200;
@ -113,6 +111,11 @@ class Sort extends PureComponent {
).start(() => close()); ).start(() => close());
} }
renderCheck = () => {
const { theme } = this.props;
return <List.Icon name='check' color={themes[theme].tintColor} />;
}
render() { render() {
const { isMasterDetail, insets } = this.props; const { isMasterDetail, insets } = this.props;
const statusBarHeight = insets?.top ?? 0; const statusBarHeight = insets?.top ?? 0;
@ -150,58 +153,50 @@ class Sort extends PureComponent {
} }
]} ]}
> >
<Touch <List.Item
title={I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}
left={() => <List.Icon name='sort' />}
color={themes[theme].auxiliaryText}
onPress={this.close} onPress={this.close}
theme={theme} translateTitle={false}
> />
<View style={[styles.dropdownContainerHeader, { borderColor: themes[theme].separatorColor }]}> <List.Separator />
<View style={styles.sortItemContainer}> <List.Item
<CustomIcon style={[styles.sortIcon, { color: themes[theme].auxiliaryText }]} size={22} name='sort' /> title='Alphabetical'
<Text style={[styles.sortToggleText, { color: themes[theme].auxiliaryText }]}>{I18n.t('Sorting_by', { key: I18n.t(sortBy === 'alphabetical' ? 'name' : 'activity') })}</Text> left={() => <List.Icon name='sort-az' />}
</View> color={themes[theme].auxiliaryText}
</View> onPress={this.sortByName}
</Touch> right={() => (sortBy === 'alphabetical' ? this.renderCheck() : null)}
<SortItemButton onPress={this.sortByName} theme={theme}> />
<SortItemContent <List.Item
icon='sort-az' title='Activity'
label='Alphabetical' left={() => <List.Icon name='clock' />}
checked={sortBy === 'alphabetical'} color={themes[theme].auxiliaryText}
theme={theme} onPress={this.sortByActivity}
/> right={() => (sortBy === 'activity' ? this.renderCheck() : null)}
</SortItemButton> />
<SortItemButton onPress={this.sortByActivity} theme={theme}> <List.Separator />
<SortItemContent <List.Item
icon='clock' title='Group_by_type'
label='Activity' left={() => <List.Icon name='group-by-type' />}
checked={sortBy === 'activity'} color={themes[theme].auxiliaryText}
theme={theme} onPress={this.toggleGroupByType}
/> right={() => (groupByType ? this.renderCheck() : null)}
</SortItemButton> />
<View style={[styles.sortSeparator, { backgroundColor: themes[theme].separatorColor }]} /> <List.Item
<SortItemButton onPress={this.toggleGroupByType} theme={theme}> title='Group_by_favorites'
<SortItemContent left={() => <List.Icon name='star' />}
icon='group-by-type' color={themes[theme].auxiliaryText}
label='Group_by_type' onPress={this.toggleGroupByFavorites}
checked={groupByType} right={() => (showFavorites ? this.renderCheck() : null)}
theme={theme} />
/> <List.Item
</SortItemButton> title='Unread_on_top'
<SortItemButton onPress={this.toggleGroupByFavorites} theme={theme}> left={() => <List.Icon name='unread-on-top-disabled' />}
<SortItemContent color={themes[theme].auxiliaryText}
icon='star' onPress={this.toggleUnread}
label='Group_by_favorites' right={() => (showUnread ? this.renderCheck() : null)}
checked={showFavorites} />
theme={theme}
/>
</SortItemButton>
<SortItemButton onPress={this.toggleUnread} theme={theme}>
<SortItemContent
icon='unread-on-top-disabled'
label='Unread_on_top'
checked={showUnread}
theme={theme}
/>
</SortItemButton>
</Animated.View> </Animated.View>
</> </>
); );

View File

@ -15,56 +15,22 @@ export default StyleSheet.create({
alignItems: 'center', alignItems: 'center',
flexDirection: 'row' flexDirection: 'row'
}, },
sortToggleContainerClose: {
position: 'absolute',
top: 0,
width: '100%'
},
sortToggleText: {
fontSize: 16,
flex: 1,
...sharedStyles.textRegular
},
queueToggleText: {
fontSize: 16,
flex: 1,
...sharedStyles.textRegular
},
dropdownContainer: { dropdownContainer: {
width: '100%', width: '100%',
position: 'absolute', position: 'absolute',
top: 0, top: 0,
borderBottomWidth: StyleSheet.hairlineWidth borderBottomWidth: StyleSheet.hairlineWidth
}, },
sortItemButton: {
height: 57,
justifyContent: 'center'
},
sortItemContainer: {
flexDirection: 'row',
alignItems: 'center'
},
sortItemText: {
fontSize: 18,
flex: 1,
...sharedStyles.textRegular
},
backdrop: { backdrop: {
...StyleSheet.absoluteFill ...StyleSheet.absoluteFill
}, },
sortSeparator: {
height: StyleSheet.hairlineWidth,
marginHorizontal: 12,
flex: 1
},
sortIcon: {
width: 22,
height: 22,
marginHorizontal: 12
},
queueIcon: { queueIcon: {
marginHorizontal: 12 marginHorizontal: 12
}, },
omnichannelRightContainer: {
flexDirection: 'row',
alignItems: 'center'
},
groupTitleContainer: { groupTitleContainer: {
paddingHorizontal: 12, paddingHorizontal: 12,
paddingTop: 17, paddingTop: 17,
@ -90,56 +56,5 @@ export default StyleSheet.create({
marginRight: 12, marginRight: 12,
paddingVertical: 10, paddingVertical: 10,
...sharedStyles.textRegular ...sharedStyles.textRegular
},
serverItem: {
height: 68
},
serverItemContainer: {
flexDirection: 'row',
alignItems: 'center',
height: 68
},
serverIcon: {
width: 42,
height: 42,
marginHorizontal: 12,
marginVertical: 13,
borderRadius: 4,
resizeMode: 'contain'
},
serverTextContainer: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center'
},
serverName: {
fontSize: 18,
...sharedStyles.textSemibold
},
serverUrl: {
fontSize: 16,
...sharedStyles.textRegular
},
serverSeparator: {
height: StyleSheet.hairlineWidth,
marginLeft: 72
},
encryptionButton: {
width: '100%',
flexDirection: 'row',
alignItems: 'center',
padding: 12
},
encryptionIcon: {
...sharedStyles.textMedium
},
encryptionText: {
flex: 1,
fontSize: 16,
marginHorizontal: 16,
...sharedStyles.textMedium
},
omnichannelToggle: {
marginRight: 12
} }
}); });

View File

@ -111,11 +111,20 @@ stories.add('with icon', () => (
</List.Container> </List.Container>
)); ));
stories.add('with custom color', () => ( stories.add('with custom colors', () => (
<List.Container> <List.Container>
<List.Separator /> <List.Separator />
<List.Item title='Chats' color='red' /> <List.Item title='Chats' color='red' />
<List.Separator /> <List.Separator />
<List.Item
title='Press me!'
color='white'
onPress={() => alert('Press')}
backgroundColor='red'
underlayColor='green'
translateTitle={false}
/>
<List.Separator />
</List.Container> </List.Container>
)); ));