[MM-22948] - Improve unread badge UI on the hamburger menu and team icons (#4635)
* updates to bage UI * fixed spacing * updated tests with npm test command * fixed badge theme colors * updated badge width to deal with larger mention counts * updated tests * fixed sizing issue * fixed sizing issue & moved maxWidth to Badge layout * added constants for badge maxWidth & adjusted badge position * adjusted top position for badge on burger menu * fixed last issue for max mentions positioning on burger menu badge
This commit is contained in:
parent
40a264a4de
commit
169ed80243
8 changed files with 99 additions and 21 deletions
|
|
@ -11,6 +11,7 @@ import {
|
|||
View,
|
||||
ViewPropTypes,
|
||||
} from 'react-native';
|
||||
import {CHANNEL_ITEM_LARGE_BADGE_MAX_WIDTH, CHANNEL_ITEM_SMALL_BADGE_MAX_WIDTH, LARGE_BADGE_MAX_WIDTH, SMALL_BADGE_MAX_WIDTH} from '@constants/view';
|
||||
|
||||
export default class Badge extends PureComponent {
|
||||
static defaultProps = {
|
||||
|
|
@ -27,6 +28,7 @@ export default class Badge extends PureComponent {
|
|||
countStyle: Text.propTypes.style,
|
||||
minHeight: PropTypes.number,
|
||||
minWidth: PropTypes.number,
|
||||
isChannelItem: PropTypes.bool,
|
||||
onPress: PropTypes.func,
|
||||
};
|
||||
|
||||
|
|
@ -78,6 +80,12 @@ export default class Badge extends PureComponent {
|
|||
onLayout = (e) => {
|
||||
if (!this.layoutReady) {
|
||||
let width;
|
||||
let maxWidth;
|
||||
if (this.props.isChannelItem) {
|
||||
maxWidth = this.props.count > 99 ? CHANNEL_ITEM_LARGE_BADGE_MAX_WIDTH : CHANNEL_ITEM_SMALL_BADGE_MAX_WIDTH;
|
||||
} else {
|
||||
maxWidth = this.props.count > 99 ? LARGE_BADGE_MAX_WIDTH : SMALL_BADGE_MAX_WIDTH;
|
||||
}
|
||||
|
||||
if (e.nativeEvent.layout.width <= e.nativeEvent.layout.height) {
|
||||
width = e.nativeEvent.layout.height;
|
||||
|
|
@ -86,11 +94,13 @@ export default class Badge extends PureComponent {
|
|||
}
|
||||
width = Math.max(this.props.count < 10 ? width : width + 10, this.props.minWidth);
|
||||
const borderRadius = width / 2;
|
||||
|
||||
this.setNativeProps({
|
||||
style: {
|
||||
width,
|
||||
borderRadius,
|
||||
opacity: 1,
|
||||
maxWidth,
|
||||
},
|
||||
});
|
||||
this.layoutReady = true;
|
||||
|
|
@ -106,11 +116,7 @@ export default class Badge extends PureComponent {
|
|||
<View
|
||||
style={[styles.text, this.props.countStyle]}
|
||||
onLayout={this.onLayout}
|
||||
>
|
||||
<View style={styles.verticalAlign}>
|
||||
<View style={[styles.unreadIndicator, {backgroundColor: this.props.countStyle.color}]}/>
|
||||
</View>
|
||||
</View>
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
let mentionCount = count;
|
||||
|
|
|
|||
|
|
@ -965,9 +965,11 @@ exports[`ChannelItem should match snapshot with mentions and muted 1`] = `
|
|||
Object {
|
||||
"color": "#145dbf",
|
||||
"fontSize": 12,
|
||||
"fontWeight": "bold",
|
||||
}
|
||||
}
|
||||
extraPaddingHorizontal={10}
|
||||
isChannelItem={true}
|
||||
minHeight={20}
|
||||
minWidth={21}
|
||||
onPress={[Function]}
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ export default class ChannelItem extends PureComponent {
|
|||
count={mentions}
|
||||
onPress={this.onPress}
|
||||
minWidth={21}
|
||||
isChannelItem={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -246,6 +247,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
mention: {
|
||||
color: theme.mentionColor,
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
muted: {
|
||||
opacity: 0.5,
|
||||
|
|
|
|||
|
|
@ -46,12 +46,17 @@ export default class SwitchTeamsButton extends React.PureComponent {
|
|||
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const lowMentionCount = mentionCount <= 0;
|
||||
const minWidth = lowMentionCount ? 8 : 20;
|
||||
const badgeStyle = lowMentionCount ? styles.smallBadge : styles.badge;
|
||||
const containerStyle = lowMentionCount ? styles.smallBadgeContainer : styles.badgeContainer;
|
||||
|
||||
const badge = (
|
||||
<Badge
|
||||
containerStyle={styles.badgeContainer}
|
||||
style={styles.badge}
|
||||
containerStyle={containerStyle}
|
||||
style={badgeStyle}
|
||||
countStyle={styles.mention}
|
||||
minWidth={20}
|
||||
minWidth={minWidth}
|
||||
count={mentionCount}
|
||||
/>
|
||||
);
|
||||
|
|
@ -89,6 +94,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
height: 20,
|
||||
padding: 3,
|
||||
},
|
||||
smallBadge: {
|
||||
backgroundColor: theme.mentionBg,
|
||||
height: 8,
|
||||
padding: 3,
|
||||
},
|
||||
badgeContainer: {
|
||||
borderColor: theme.sidebarBg,
|
||||
borderRadius: 14,
|
||||
|
|
@ -97,9 +107,18 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
right: 0,
|
||||
top: -9,
|
||||
},
|
||||
smallBadgeContainer: {
|
||||
borderColor: theme.sidebarBg,
|
||||
borderRadius: 14,
|
||||
borderWidth: 2,
|
||||
position: 'absolute',
|
||||
right: 6,
|
||||
top: -5,
|
||||
},
|
||||
mention: {
|
||||
color: theme.mentionColor,
|
||||
fontSize: 10,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
switcherArrow: {
|
||||
color: theme.sidebarHeaderBg,
|
||||
|
|
|
|||
|
|
@ -46,13 +46,18 @@ export default class TeamsListItem extends React.PureComponent {
|
|||
} = this.props;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const lowMentionCount = mentionCount <= 0;
|
||||
const minWidth = lowMentionCount ? 8 : 20;
|
||||
const badgeStyle = lowMentionCount ? styles.smallBadge : styles.badge;
|
||||
const containerStyle = lowMentionCount ? styles.smallBadgeContainer : styles.badgeContainer;
|
||||
|
||||
const badge = (
|
||||
<Badge
|
||||
containerStyle={styles.badgeContainer}
|
||||
containerStyle={containerStyle}
|
||||
countStyle={styles.mention}
|
||||
count={mentionCount}
|
||||
minWidth={20}
|
||||
style={styles.badge}
|
||||
minWidth={minWidth}
|
||||
style={badgeStyle}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
@ -152,6 +157,11 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
height: 20,
|
||||
padding: 3,
|
||||
},
|
||||
smallBadge: {
|
||||
backgroundColor: theme.mentionBg,
|
||||
height: 8,
|
||||
padding: 3,
|
||||
},
|
||||
badgeContainer: {
|
||||
borderColor: theme.sidebarBg,
|
||||
borderRadius: 14,
|
||||
|
|
@ -160,9 +170,18 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
right: -12,
|
||||
top: -10,
|
||||
},
|
||||
smallBadgeContainer: {
|
||||
borderColor: theme.sidebarBg,
|
||||
borderRadius: 14,
|
||||
borderWidth: 2,
|
||||
position: 'absolute',
|
||||
right: -7,
|
||||
top: -6,
|
||||
},
|
||||
mention: {
|
||||
color: theme.mentionColor,
|
||||
fontSize: 10,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -36,6 +36,14 @@ export const NotificationLevels = {
|
|||
export const NOTIFY_ALL_MEMBERS = 5;
|
||||
export const INDICATOR_BAR_HEIGHT = 38;
|
||||
|
||||
export const CHANNEL_ITEM_LARGE_BADGE_MAX_WIDTH = 38;
|
||||
export const CHANNEL_ITEM_SMALL_BADGE_MAX_WIDTH = 32;
|
||||
export const LARGE_BADGE_MAX_WIDTH = 30;
|
||||
export const SMALL_BADGE_MAX_WIDTH = 26;
|
||||
export const MAX_BADGE_RIGHT_POSITION = -17;
|
||||
export const LARGE_BADGE_RIGHT_POSITION = -16;
|
||||
export const SMALL_BADGE_RIGHT_POSITION = -13;
|
||||
|
||||
const ViewTypes = keyMirror({
|
||||
DATA_CLEANUP: null,
|
||||
SERVER_URL_CHANGED: null,
|
||||
|
|
|
|||
|
|
@ -79,8 +79,8 @@ exports[`ChannelDrawerButton should match, full snapshot 2`] = `
|
|||
"borderRadius": 14,
|
||||
"borderWidth": 2,
|
||||
"position": "absolute",
|
||||
"right": -14,
|
||||
"top": -7,
|
||||
"right": -13,
|
||||
"top": -6,
|
||||
}
|
||||
}
|
||||
count={1}
|
||||
|
|
@ -88,16 +88,17 @@ exports[`ChannelDrawerButton should match, full snapshot 2`] = `
|
|||
Object {
|
||||
"color": "#145dbf",
|
||||
"fontSize": 10,
|
||||
"fontWeight": "bold",
|
||||
}
|
||||
}
|
||||
extraPaddingHorizontal={10}
|
||||
minHeight={20}
|
||||
minWidth={19}
|
||||
minWidth={18}
|
||||
onPress={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"backgroundColor": "#ffffff",
|
||||
"height": 19,
|
||||
"height": 18,
|
||||
"padding": 3,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import {t} from 'app/utils/i18n';
|
|||
import {intlShape} from 'react-intl';
|
||||
|
||||
import telemetry from 'app/telemetry';
|
||||
import {LARGE_BADGE_RIGHT_POSITION, SMALL_BADGE_RIGHT_POSITION, MAX_BADGE_RIGHT_POSITION} from '@constants/view';
|
||||
|
||||
export default class ChannelDrawerButton extends PureComponent {
|
||||
static propTypes = {
|
||||
|
|
@ -87,14 +88,21 @@ export default class ChannelDrawerButton extends PureComponent {
|
|||
|
||||
let badge;
|
||||
if (badgeCount && visible) {
|
||||
const badgeCountLow = badgeCount <= 0;
|
||||
const minWidth = badgeCountLow ? 8 : 18;
|
||||
const badgeStyle = badgeCountLow ? style.smallBadge : style.badge;
|
||||
const smallBadgeRightPosition = badgeCount > 9 ? LARGE_BADGE_RIGHT_POSITION : SMALL_BADGE_RIGHT_POSITION;
|
||||
const rightStylePosition = badgeCount > 99 ? MAX_BADGE_RIGHT_POSITION : smallBadgeRightPosition;
|
||||
const containerStyle = badgeCountLow ? style.smallBadgeContainer : {...style.badgeContainer, right: rightStylePosition};
|
||||
|
||||
badge = (
|
||||
<Badge
|
||||
containerStyle={style.badgeContainer}
|
||||
style={style.badge}
|
||||
containerStyle={containerStyle}
|
||||
style={badgeStyle}
|
||||
countStyle={style.mention}
|
||||
count={badgeCount}
|
||||
onPress={this.handlePress}
|
||||
minWidth={19}
|
||||
minWidth={minWidth}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -155,7 +163,12 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
},
|
||||
badge: {
|
||||
backgroundColor: theme.mentionBg,
|
||||
height: 19,
|
||||
height: 18,
|
||||
padding: 3,
|
||||
},
|
||||
smallBadge: {
|
||||
backgroundColor: theme.mentionBg,
|
||||
height: 8,
|
||||
padding: 3,
|
||||
},
|
||||
badgeContainer: {
|
||||
|
|
@ -163,12 +176,20 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
|
|||
borderRadius: 14,
|
||||
borderWidth: 2,
|
||||
position: 'absolute',
|
||||
right: -14,
|
||||
top: -7,
|
||||
top: -6,
|
||||
},
|
||||
smallBadgeContainer: {
|
||||
borderColor: theme.sidebarHeaderBg,
|
||||
borderRadius: 14,
|
||||
borderWidth: 2,
|
||||
position: 'absolute',
|
||||
right: -7,
|
||||
top: 0,
|
||||
},
|
||||
mention: {
|
||||
color: theme.mentionColor,
|
||||
fontSize: 10,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue