React-native-ui-kitten: Badge

Created on 4 Feb 2020  路  4Comments  路  Source: akveo/react-native-ui-kitten

馃殌 Feature Proposal

Hey.
It would be great if you added the ability to add to Bottom Navigation
"Badge".

Example

https://imgur.com/bKniATG
https://react-native-elements.github.io/react-native-elements/docs/badge.html

Proposal Components

Most helpful comment

Yes, it turned out to be done.
Created a wrapper over the BottomNavigationTab component

interface ComponentProps {
  badgeText?: string;
}

export type EmptyDataProps = ThemedComponentProps & BottomNavigationTabProps & ComponentProps;

interface State {
}

class EmptyDataContainer extends React.PureComponent<EmptyDataProps, State> {

  constructor(props: EmptyDataProps) {
    super(props);
    this.state = {};
  }

  public render(): React.ReactNode {
    const {themedStyle, title, icon, titleStyle, selected, badgeText, onSelect} = this.props;

    return (
      <View style={themedStyle.container}>
        <BottomNavigationTab
          titleStyle={titleStyle}
          selected={selected}
          onSelect={onSelect}
          title={title}
          icon={icon}
        />
        {
          badgeText &&
          <View style={themedStyle.badge}>
            <Text style={themedStyle.badgeText}>
              {badgeText}
            </Text>
          </View>
        }
      </View>
    );
  }
}

export const CustomBottomNavigationTab = withStyles(EmptyDataContainer, (theme: ThemeType) => ({
  container: {
    flex: 1,
  },
  badge: {
    position: 'absolute',
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    width: '100%'
  },
  badgeText: {
    ...textStyle.headline,
    borderWidth: 2,
    borderColor: Colors.white,
    padding: 2,
    backgroundColor: 'red',
    borderRadius: 20,
    fontSize: 9,
    lineHeight: 11,
    color: Colors.white,
    minWidth: 19,
    textAlignVertical: 'center',
    textAlign: 'center',
    left: 10,
    top: -2,
  },
}));

All 4 comments

Hi @stanislavpoleshuk, thanks for the proposal. Is there any workaround to achieve this currently?

Yes, it turned out to be done.
Created a wrapper over the BottomNavigationTab component

interface ComponentProps {
  badgeText?: string;
}

export type EmptyDataProps = ThemedComponentProps & BottomNavigationTabProps & ComponentProps;

interface State {
}

class EmptyDataContainer extends React.PureComponent<EmptyDataProps, State> {

  constructor(props: EmptyDataProps) {
    super(props);
    this.state = {};
  }

  public render(): React.ReactNode {
    const {themedStyle, title, icon, titleStyle, selected, badgeText, onSelect} = this.props;

    return (
      <View style={themedStyle.container}>
        <BottomNavigationTab
          titleStyle={titleStyle}
          selected={selected}
          onSelect={onSelect}
          title={title}
          icon={icon}
        />
        {
          badgeText &&
          <View style={themedStyle.badge}>
            <Text style={themedStyle.badgeText}>
              {badgeText}
            </Text>
          </View>
        }
      </View>
    );
  }
}

export const CustomBottomNavigationTab = withStyles(EmptyDataContainer, (theme: ThemeType) => ({
  container: {
    flex: 1,
  },
  badge: {
    position: 'absolute',
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    width: '100%'
  },
  badgeText: {
    ...textStyle.headline,
    borderWidth: 2,
    borderColor: Colors.white,
    padding: 2,
    backgroundColor: 'red',
    borderRadius: 20,
    fontSize: 9,
    lineHeight: 11,
    color: Colors.white,
    minWidth: 19,
    textAlignVertical: 'center',
    textAlign: 'center',
    left: 10,
    top: -2,
  },
}));

Yes, it turned out to be done.
Created a wrapper over the BottomNavigationTab component

interface ComponentProps {
  badgeText?: string;
}

export type EmptyDataProps = ThemedComponentProps & BottomNavigationTabProps & ComponentProps;

interface State {
}

class EmptyDataContainer extends React.PureComponent<EmptyDataProps, State> {

  constructor(props: EmptyDataProps) {
    super(props);
    this.state = {};
  }

  public render(): React.ReactNode {
    const {themedStyle, title, icon, titleStyle, selected, badgeText, onSelect} = this.props;

    return (
      <View style={themedStyle.container}>
        <BottomNavigationTab
          titleStyle={titleStyle}
          selected={selected}
          onSelect={onSelect}
          title={title}
          icon={icon}
        />
        {
          badgeText &&
          <View style={themedStyle.badge}>
            <Text style={themedStyle.badgeText}>
              {badgeText}
            </Text>
          </View>
        }
      </View>
    );
  }
}

export const CustomBottomNavigationTab = withStyles(EmptyDataContainer, (theme: ThemeType) => ({
  container: {
    flex: 1,
  },
  badge: {
    position: 'absolute',
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    width: '100%'
  },
  badgeText: {
    ...textStyle.headline,
    borderWidth: 2,
    borderColor: Colors.white,
    padding: 2,
    backgroundColor: 'red',
    borderRadius: 20,
    fontSize: 9,
    lineHeight: 11,
    color: Colors.white,
    minWidth: 19,
    textAlignVertical: 'center',
    textAlign: 'center',
    left: 10,
    top: -2,
  },
}));

Has anyone actually made this work? For me it displays, but clicking the Tab does nothing.

You don't actually need any fancy stuff to add a badge (as it turns out). Consider something like this:

// ...
const selectedIndex: number = 0;
const colors = {primary: 'blue'}; 
const unreadNotifications: number = 3; 
// ... 
<BottomNavigationTab
        icon={(props) => (
          <View>
            <Icon
              {...props}
              name="bell-outline"
              fill={selectedIndex == 0 ? colors.primary : "grey"}
            />
            <View
              style={{
                height: 15,
                width: 15,
                backgroundColor: "red",
                borderRadius: 10,
                position: "absolute",
                right: 0,
              }}
            >
              <Text
                style={{ color: "#fff", textAlign: "center", fontSize: 10 }}
              >
                {unreadNotifications}
              </Text>
            </View>
          </View>
        )}
      />

unreadNotifications is a number, and in this example the icon fill is determined by the footer state. But the point remains: you can just make the BottomNavigationTab render a custom View with its icon prop.

As such, you can make the presence of the badge view and the unreadNotifications to be functions of state.

Was this page helpful?
0 / 5 - 0 ratings