Skip to content

Feat/ support multiple buttons on Modal.TopBar #2011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 26, 2022
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
56 changes: 41 additions & 15 deletions demo/src/screens/componentScreens/ModalScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, {Component} from 'react';
import {Alert, StyleSheet} from 'react-native';
import {Navigation} from 'react-native-navigation';
import {Colors, Carousel, PageControl, Modal, View, Text} from 'react-native-ui-lib'; // eslint-disable-line
import {Colors, Carousel, PageControl, Modal, View, Text, Assets} from 'react-native-ui-lib'; // eslint-disable-line

const BUTTONS_HIT_SLOP = {right: 5, left: 5, top: 10, bottom: 10};
interface ModalScreenProps {
componentId: string;
}
Expand All @@ -12,7 +13,6 @@ interface State {
}

export default class ModalScreen extends Component<ModalScreenProps, State> {

static options() {
return {
topBar: {
Expand All @@ -39,7 +39,7 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
<View flex>
<PageControl
containerStyle={[styles.pageControl, styles.absoluteContainer]}
numOfPages={4}
numOfPages={5}
currentPage={this.state.currentPage}
color={Colors.grey10}
size={15}
Expand All @@ -55,12 +55,8 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
}}
/>
<View padding-20>
<Text text70>
This is an example of a custom modal top bar.
</Text>
<Text text70>
By default you get the &apos;x&apos; cancel icon and &apos;save&apos; as done label
</Text>
<Text text70>This is an example of a custom modal top bar.</Text>
<Text text70>By default you get the &apos;x&apos; cancel icon and &apos;save&apos; as done label</Text>
</View>
</View>

Expand All @@ -74,8 +70,8 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
/>
<View padding-20>
<Text text70>
You can of course change it by changing the values of
cancelIcon, cancelLabel, doneIcon, doneLabel and other props..
You can of course change it by changing the values of cancelIcon, cancelLabel, doneIcon, doneLabel and
other props..
</Text>
</View>
</View>
Expand All @@ -89,9 +85,7 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
cancelLabel="back"
/>
<View padding-20>
<Text text70>
Sending onDone/onCancel is required for rendering done/cancel actions
</Text>
<Text text70>Sending onDone/onCancel is required for rendering done/cancel actions</Text>
</View>
</View>

Expand All @@ -105,7 +99,39 @@ export default class ModalScreen extends Component<ModalScreenProps, State> {
/>
<View padding-20>
<Text text70>
use doneButtonProps/cancelButtonProps properties to have custom behaviour or style for done/cancel actions
use doneButtonProps/cancelButtonProps properties to have custom behaviour or style for done/cancel
actions
</Text>
</View>
</View>

<View bg-yellow80 flex style={styles.page}>
<Modal.TopBar
title="custom button"
rightButtons={[
{
label: 'save',
buttonProps: {labelStyle: {color: Colors.yellow10, marginRight: 14}},
onPress: () => Alert.alert('save')
},
{
icon: Assets.icons.demo.settings,
onPress: () => Alert.alert('settings'),
buttonProps: {hitSlop: BUTTONS_HIT_SLOP, iconStyle: {tintColor: Colors.yellow10}}
}
]}
leftButtons={[
{
icon: Assets.icons.x,
onPress: () => Alert.alert('back'),
buttonProps: {hitSlop: BUTTONS_HIT_SLOP, iconStyle: {tintColor: Colors.yellow10}}
}
]}
/>
<View padding-20>
<Text text70>
This is an example for using the rightButtons and leftButtons props for having more than one button each
side
</Text>
</View>
</View>
Expand Down
38 changes: 32 additions & 6 deletions src/components/modal/TopBar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _ from 'lodash';
import React, {Component} from 'react';
import {StyleSheet, StyleProp, TextStyle, ImageSourcePropType} from 'react-native';
import {Constants, asBaseComponent} from '../../commons/new';
Expand Down Expand Up @@ -48,6 +49,14 @@ export interface ModalTopBarProps {
* cancel action callback
*/
onCancel?: (props?: any) => void;
/**
* buttons to render on the right side of the top bar
*/
rightButtons?: topBarButtonProp | topBarButtonProp[];
/**
* buttons to render on the left side of the top bar
*/
leftButtons?: topBarButtonProp | topBarButtonProp[];
/**
* whether to include status bar or not (height claculations)
*/
Expand Down Expand Up @@ -92,21 +101,18 @@ class TopBar extends Component<ModalTopBarProps> {

renderTopBarButton({onPress, label, icon, accessibilityLabel, buttonProps}: topBarButtonProp) {
if (onPress && (label || icon)) {
// @ts-ignore
const {iconStyle, labelStyle, ...otherButtonProps} = buttonProps;

return (
<Button
link
onPress={onPress}
label={label}
labelStyle={[styles.actionLabel, labelStyle]}
labelStyle={[styles.actionLabel, buttonProps?.labelStyle]}
iconSource={icon}
iconStyle={[styles.icon, iconStyle]}
iconStyle={[styles.icon, buttonProps?.iconStyle]}
{...DEFAULT_BUTTON_PROPS}
accessibilityLabel={accessibilityLabel}
{...otherButtonProps}
hitSlop={{top: 10, bottom: 10, left: 20, right: 20}}
{...buttonProps}
/>
);
}
Expand Down Expand Up @@ -134,6 +140,24 @@ class TopBar extends Component<ModalTopBarProps> {
});
}

renderLeftButtons = () => {
const {leftButtons} = this.props;
if (_.isArray(leftButtons)) {
return _.map(leftButtons, button => this.renderTopBarButton(button));
} else {
return leftButtons && this.renderTopBarButton(leftButtons);
}
};

renderRightButtons = () => {
const {rightButtons} = this.props;
if (_.isArray(rightButtons)) {
return _.map(rightButtons, button => this.renderTopBarButton(button));
} else {
return rightButtons && this.renderTopBarButton(rightButtons);
}
};

render() {
const {title, titleStyle, includeStatusBar, containerStyle, useSafeArea} = this.props;

Expand All @@ -143,13 +167,15 @@ class TopBar extends Component<ModalTopBarProps> {
<View style={styles.container}>
<View row flex bottom paddingL-15 centerV>
{this.renderCancel()}
{this.renderLeftButtons()}
</View>
<View row flex-3 bottom centerH centerV>
<Text accessible={!!title} numberOfLines={1} text70 style={[styles.title, titleStyle]}>
{title}
</Text>
</View>
<View row flex bottom right paddingR-15 centerV>
{this.renderRightButtons()}
{this.renderDone()}
</View>
</View>
Expand Down
10 changes: 10 additions & 0 deletions src/components/modal/api/modalTopBar.api.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@
"default": "Assets.icons.x"
},
{"name": "onCancel", "type": "(props?: any) => void", "description": "Cancel action callback"},
{
"name": "rightButtons",
"type": "topBarButtonProp | topBarButtonProp[]",
"description": "Buttons to render on the right side of the top bar"
},
{
"name": "leftButtons",
"type": "topBarButtonProp | topBarButtonProp[]",
"description": "Buttons to render on the left side of the top bar"
},
{
"name": "includeStatusBar",
"type": "boolean",
Expand Down