Skip to content

Commit 1072e9a

Browse files
authored
Feat/ support multiple buttons on ModalTopBar (#2011)
1 parent 176aa5f commit 1072e9a

File tree

3 files changed

+83
-21
lines changed

3 files changed

+83
-21
lines changed

demo/src/screens/componentScreens/ModalScreen.tsx

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import React, {Component} from 'react';
22
import {Alert, StyleSheet} from 'react-native';
33
import {Navigation} from 'react-native-navigation';
4-
import {Colors, Carousel, PageControl, Modal, View, Text} from 'react-native-ui-lib'; // eslint-disable-line
4+
import {Colors, Carousel, PageControl, Modal, View, Text, Assets} from 'react-native-ui-lib'; // eslint-disable-line
55

6+
const BUTTONS_HIT_SLOP = {right: 5, left: 5, top: 10, bottom: 10};
67
interface ModalScreenProps {
78
componentId: string;
89
}
@@ -12,7 +13,6 @@ interface State {
1213
}
1314

1415
export default class ModalScreen extends Component<ModalScreenProps, State> {
15-
1616
static options() {
1717
return {
1818
topBar: {
@@ -39,7 +39,7 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
3939
<View flex>
4040
<PageControl
4141
containerStyle={[styles.pageControl, styles.absoluteContainer]}
42-
numOfPages={4}
42+
numOfPages={5}
4343
currentPage={this.state.currentPage}
4444
color={Colors.grey10}
4545
size={15}
@@ -55,12 +55,8 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
5555
}}
5656
/>
5757
<View padding-20>
58-
<Text text70>
59-
This is an example of a custom modal top bar.
60-
</Text>
61-
<Text text70>
62-
By default you get the &apos;x&apos; cancel icon and &apos;save&apos; as done label
63-
</Text>
58+
<Text text70>This is an example of a custom modal top bar.</Text>
59+
<Text text70>By default you get the &apos;x&apos; cancel icon and &apos;save&apos; as done label</Text>
6460
</View>
6561
</View>
6662

@@ -74,8 +70,8 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
7470
/>
7571
<View padding-20>
7672
<Text text70>
77-
You can of course change it by changing the values of
78-
cancelIcon, cancelLabel, doneIcon, doneLabel and other props..
73+
You can of course change it by changing the values of cancelIcon, cancelLabel, doneIcon, doneLabel and
74+
other props..
7975
</Text>
8076
</View>
8177
</View>
@@ -89,9 +85,7 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
8985
cancelLabel="back"
9086
/>
9187
<View padding-20>
92-
<Text text70>
93-
Sending onDone/onCancel is required for rendering done/cancel actions
94-
</Text>
88+
<Text text70>Sending onDone/onCancel is required for rendering done/cancel actions</Text>
9589
</View>
9690
</View>
9791

@@ -105,7 +99,39 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
10599
/>
106100
<View padding-20>
107101
<Text text70>
108-
use doneButtonProps/cancelButtonProps properties to have custom behaviour or style for done/cancel actions
102+
use doneButtonProps/cancelButtonProps properties to have custom behaviour or style for done/cancel
103+
actions
104+
</Text>
105+
</View>
106+
</View>
107+
108+
<View bg-yellow80 flex style={styles.page}>
109+
<Modal.TopBar
110+
title="custom button"
111+
rightButtons={[
112+
{
113+
label: 'save',
114+
buttonProps: {labelStyle: {color: Colors.yellow10, marginRight: 14}},
115+
onPress: () => Alert.alert('save')
116+
},
117+
{
118+
icon: Assets.icons.demo.settings,
119+
onPress: () => Alert.alert('settings'),
120+
buttonProps: {hitSlop: BUTTONS_HIT_SLOP, iconStyle: {tintColor: Colors.yellow10}}
121+
}
122+
]}
123+
leftButtons={[
124+
{
125+
icon: Assets.icons.x,
126+
onPress: () => Alert.alert('back'),
127+
buttonProps: {hitSlop: BUTTONS_HIT_SLOP, iconStyle: {tintColor: Colors.yellow10}}
128+
}
129+
]}
130+
/>
131+
<View padding-20>
132+
<Text text70>
133+
This is an example for using the rightButtons and leftButtons props for having more than one button each
134+
side
109135
</Text>
110136
</View>
111137
</View>

src/components/modal/TopBar.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import _ from 'lodash';
12
import React, {Component} from 'react';
23
import {StyleSheet, StyleProp, TextStyle, ImageSourcePropType} from 'react-native';
34
import {Constants, asBaseComponent} from '../../commons/new';
@@ -48,6 +49,14 @@ export interface ModalTopBarProps {
4849
* cancel action callback
4950
*/
5051
onCancel?: (props?: any) => void;
52+
/**
53+
* buttons to render on the right side of the top bar
54+
*/
55+
rightButtons?: topBarButtonProp | topBarButtonProp[];
56+
/**
57+
* buttons to render on the left side of the top bar
58+
*/
59+
leftButtons?: topBarButtonProp | topBarButtonProp[];
5160
/**
5261
* whether to include status bar or not (height claculations)
5362
*/
@@ -92,21 +101,18 @@ class TopBar extends Component<ModalTopBarProps> {
92101

93102
renderTopBarButton({onPress, label, icon, accessibilityLabel, buttonProps}: topBarButtonProp) {
94103
if (onPress && (label || icon)) {
95-
// @ts-ignore
96-
const {iconStyle, labelStyle, ...otherButtonProps} = buttonProps;
97-
98104
return (
99105
<Button
100106
link
101107
onPress={onPress}
102108
label={label}
103-
labelStyle={[styles.actionLabel, labelStyle]}
109+
labelStyle={[styles.actionLabel, buttonProps?.labelStyle]}
104110
iconSource={icon}
105-
iconStyle={[styles.icon, iconStyle]}
111+
iconStyle={[styles.icon, buttonProps?.iconStyle]}
106112
{...DEFAULT_BUTTON_PROPS}
107113
accessibilityLabel={accessibilityLabel}
108-
{...otherButtonProps}
109114
hitSlop={{top: 10, bottom: 10, left: 20, right: 20}}
115+
{...buttonProps}
110116
/>
111117
);
112118
}
@@ -134,6 +140,24 @@ class TopBar extends Component<ModalTopBarProps> {
134140
});
135141
}
136142

143+
renderLeftButtons = () => {
144+
const {leftButtons} = this.props;
145+
if (_.isArray(leftButtons)) {
146+
return _.map(leftButtons, button => this.renderTopBarButton(button));
147+
} else {
148+
return leftButtons && this.renderTopBarButton(leftButtons);
149+
}
150+
};
151+
152+
renderRightButtons = () => {
153+
const {rightButtons} = this.props;
154+
if (_.isArray(rightButtons)) {
155+
return _.map(rightButtons, button => this.renderTopBarButton(button));
156+
} else {
157+
return rightButtons && this.renderTopBarButton(rightButtons);
158+
}
159+
};
160+
137161
render() {
138162
const {title, titleStyle, includeStatusBar, containerStyle, useSafeArea} = this.props;
139163

@@ -143,13 +167,15 @@ class TopBar extends Component<ModalTopBarProps> {
143167
<View style={styles.container}>
144168
<View row flex bottom paddingL-15 centerV>
145169
{this.renderCancel()}
170+
{this.renderLeftButtons()}
146171
</View>
147172
<View row flex-3 bottom centerH centerV>
148173
<Text accessible={!!title} numberOfLines={1} text70 style={[styles.title, titleStyle]}>
149174
{title}
150175
</Text>
151176
</View>
152177
<View row flex bottom right paddingR-15 centerV>
178+
{this.renderRightButtons()}
153179
{this.renderDone()}
154180
</View>
155181
</View>

src/components/modal/api/modalTopBar.api.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@
3030
"default": "Assets.icons.x"
3131
},
3232
{"name": "onCancel", "type": "(props?: any) => void", "description": "Cancel action callback"},
33+
{
34+
"name": "rightButtons",
35+
"type": "topBarButtonProp | topBarButtonProp[]",
36+
"description": "Buttons to render on the right side of the top bar"
37+
},
38+
{
39+
"name": "leftButtons",
40+
"type": "topBarButtonProp | topBarButtonProp[]",
41+
"description": "Buttons to render on the left side of the top bar"
42+
},
3343
{
3444
"name": "includeStatusBar",
3545
"type": "boolean",

0 commit comments

Comments
 (0)