Skip to content
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

badge support #70

Merged
merged 12 commits into from
Feb 11, 2018
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@ Don't skip this part. You will be happy to know about all the good stuff you can
| **`activeLabelColor`** | Text Color of the Label when the Tab is active. | `string` | `activeLabelColor` of BottomNavigation |
| **`barBackgroundColor`** | Background color for the whole component, if the tab is active. | `string` | `backgroundColor` of BottomNavigation |
| **`onPress`** | Function to be called when the Tab was pressed. **When you use this, the pressed tab won't be active automatically. You need to set it to active by updating `BottomNavigation.activeTab`.** This function will be called with the parameter `(newTabIndex) => {}` | `function` | – |

| **`badgeText`** | Text for the tab's badge. **The badge will be hidden if no badgeText is passed. isBadgeVisible can be used to override this**. | `string` | - |
| **`badgeSize`** | Size of the badge. Will be used to calculate the height, width, and border radius (height: size, width: size, borderRadius: size/2) | `number` | 20 |
| **`badgeStyle`** | Style for the badge. `badgeStyle.container` will be used to determine the badge's container style, and `badgeStyle.text` will be used to determine the badge's text style | `object` | `{ container: { position: "relative", width: 20, height: 20, borderRadius: 20 / 2, alignItems: "center", justifyContent: "center", backgroundColor: "#F50057", zIndex: 9999, bottom: 5, right: 10 }, text: { color: "#fff", fontWeight: "500", fontSize: 12 } }` |
| **`isBadgeVisible`** | Determines if the badge is visible or not | `boolean` | - |

## Behind the Navigation Bar

Expand Down
81 changes: 81 additions & 0 deletions lib/Badge.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Material badge for showing notifications, maybe more functionality in the future
* @flow
*/

import React, { Component } from 'react'
import {
View,
Text,
StyleSheet
} from 'react-native';

type BProps = {
text: string,
size: number,
children: Array<ReactElement<*>>,
style: any,
isVisible: boolean,
}

const defaultProps = {
size: 20,
isVisible: true,
style: {},
}

export default class Badge extends Component {
static defaultProps: typeof defaultProps
props: BProps
static defaultProps = defaultProps

createStyles() {
const { size, style } = this.props;
const container = Object.assign(
{},
{
position: "absolute",
width: size,
height: size,
borderRadius: size / 2,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#F50057",
zIndex: 9999,
bottom: 10,
},
style.container
);

const text = Object.assign(
{},
{
color: "#fff",
fontWeight: "500",
fontSize: 12,
},
style.text
)

return StyleSheet.create({
container,
text,
})
}

render() {
const { children, text, isVisible } = this.props;
const styles = this.createStyles();
if (!isVisible) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For android compatibility: Remove the isVisible check, lines 70-72. The check is already done in Tab.js

Copy link
Contributor Author

@ShayanJavadi ShayanJavadi Feb 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the check badgeText === undefined && !isBadgeVisible is to prevent the badge from rendering when there is no text. The check in here is for the user to be able to hide a badge even when there is text. We should keep this check

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see.

return null;
}

return (
<View>
<View style={styles.container}>
<Text style={styles.text}>{text}</Text>
</View>
</View>
)
}
}
36 changes: 31 additions & 5 deletions lib/Tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
StyleSheet,
TouchableWithoutFeedback
} from 'react-native'
import Badge from "./Badge"
import { easeInOut } from './utils/easing'


Expand All @@ -30,7 +31,11 @@ type TabProps = {
labelColor: string,
activeLabelColor?: string,
onTabPress: () => void,
onPress: () => void
onPress: () => void,
badgeText: string,
badgeSize: number,
badgeStyle: any,
isBadgeVisible: boolean,
}

type TabState = {
Expand Down Expand Up @@ -115,15 +120,33 @@ export default class Tab extends Component {
]}
>
{this._renderIcon()}
{this._renderBadge()}
{this._renderLabel()}
</View>
</TouchableWithoutFeedback>
)
}

_renderBadge = () => {
const { badgeText, badgeSize, badgeStyle, isBadgeVisible } = this.props;

if (badgeText === undefined && !isBadgeVisible) {
return null;
}

return (
<Badge
text={badgeText}
size={badgeSize}
style={badgeStyle}
isVisible={isBadgeVisible}
/>
)
}

_renderIcon = () => {
const mode = this._getModeString()
const { active, icon, activeIcon } = this.props
const mode = this._getModeString();
const { active, icon, activeIcon } = this.props;

return (
<Animated.View
Expand All @@ -133,6 +156,7 @@ export default class Tab extends Component {
{ opacity: this.state[mode].iconOpacity }
]}
>

<View ref="_bnic" collapsable={false}>
{active && activeIcon ? activeIcon : icon}
</View>
Expand Down Expand Up @@ -276,7 +300,8 @@ const styles = StyleSheet.create({
paddingBottom: 10,
paddingLeft: 12,
paddingRight: 12,
backgroundColor: 'transparent'
backgroundColor: 'transparent',
position: "relative",
},
shiftingInactiveContainer: {
maxWidth: 96,
Expand All @@ -298,6 +323,7 @@ const styles = StyleSheet.create({
includeFontPadding: false,
textAlignVertical: 'center',
justifyContent: 'flex-end',
backgroundColor: 'transparent'
backgroundColor: 'transparent',
zIndex: 0
}
})