diff --git a/README.md b/README.md index 5e838ef..2e7bda8 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/lib/Badge.js b/lib/Badge.js new file mode 100644 index 0000000..0148d32 --- /dev/null +++ b/lib/Badge.js @@ -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>, + 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) { + return null; + } + + return ( + + + {text} + + + ) + } +} diff --git a/lib/Tab.js b/lib/Tab.js index fbf1ba3..b4da627 100644 --- a/lib/Tab.js +++ b/lib/Tab.js @@ -14,6 +14,7 @@ import { StyleSheet, TouchableWithoutFeedback } from 'react-native' +import Badge from "./Badge" import { easeInOut } from './utils/easing' @@ -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 = { @@ -115,15 +120,33 @@ export default class Tab extends Component { ]} > {this._renderIcon()} + {this._renderBadge()} {this._renderLabel()} ) } + _renderBadge = () => { + const { badgeText, badgeSize, badgeStyle, isBadgeVisible } = this.props; + + if (badgeText === undefined && !isBadgeVisible) { + return null; + } + + return ( + + ) + } + _renderIcon = () => { - const mode = this._getModeString() - const { active, icon, activeIcon } = this.props + const mode = this._getModeString(); + const { active, icon, activeIcon } = this.props; return ( + {active && activeIcon ? activeIcon : icon} @@ -276,7 +300,8 @@ const styles = StyleSheet.create({ paddingBottom: 10, paddingLeft: 12, paddingRight: 12, - backgroundColor: 'transparent' + backgroundColor: 'transparent', + position: "relative", }, shiftingInactiveContainer: { maxWidth: 96, @@ -298,6 +323,7 @@ const styles = StyleSheet.create({ includeFontPadding: false, textAlignVertical: 'center', justifyContent: 'flex-end', - backgroundColor: 'transparent' + backgroundColor: 'transparent', + zIndex: 0 } })