mattermost-mobile/app/components/badge/index.tsx
Rahim Rahman 97e74c92af
feat:proper badge theme use for server list (#8313)
* fix(MM-61209): mention badge incorrect theme color

* @asaadmahmood color correction

* @asaadmahmood borderWidth 1px

* remove borderWidth: 1
2024-11-05 07:11:17 -07:00

143 lines
3.8 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import * as React from 'react';
import {Animated, Platform, type StyleProp, StyleSheet, type TextStyle} from 'react-native';
import {useTheme} from '@context/theme';
type Props = {
backgroundColor?: string;
borderColor?: string;
color?: string;
style?: Animated.WithAnimatedValue<StyleProp<TextStyle>>;
testID?: string;
type?: 'Normal' | 'Small';
/**
* Value of the `Badge` for unread dot use a negative value.
*/
value: number;
visible: boolean;
};
export default function Badge({
borderColor: borderColorProp,
color,
visible = true,
type = 'Normal',
value,
style,
testID,
...rest
}: Props) {
const [opacity] = React.useState(() => new Animated.Value(visible ? 1 : 0));
const [rendered, setRendered] = React.useState(Boolean(visible));
const theme = useTheme();
React.useEffect(() => {
if (!rendered) {
return;
}
Animated.timing(opacity, {
toValue: visible ? 1 : 0,
duration: 200,
useNativeDriver: true,
}).start(({finished}) => {
if (finished && !visible) {
setRendered(false);
}
});
}, [opacity, rendered, visible]);
if (visible && !rendered) {
setRendered(true);
}
if (!visible && !rendered) {
return null;
}
const {
backgroundColor = rest.backgroundColor || theme.mentionBg,
borderColor: styleBorderColor,
...restStyle
} = (StyleSheet.flatten(style) || {}) as TextStyle;
const borderColor = borderColorProp || styleBorderColor || theme.centerChannelBg;
const textColor = color || theme.mentionColor;
let lineHeight = Platform.select({android: 21, ios: 16.5});
let fontSize = 12;
let size = value < 0 ? 12 : 22;
let minWidth = value < 0 ? size : 26;
let additionalStyle;
if (type === 'Small') {
size = value < 0 ? 12 : 20;
lineHeight = Platform.select({android: 19, ios: 15});
fontSize = 11;
minWidth = value < 0 ? size : 24;
}
const borderRadius = size / 2;
let badge: string = value?.toString();
if (value < 0) {
badge = '';
additionalStyle = {paddingHorizontal: 0};
} else if (value < 99) {
badge = value.toString();
additionalStyle = {paddingHorizontal: 5};
} else {
badge = '99+';
additionalStyle = {paddingLeft: 4, paddingRight: 3};
}
return (
<Animated.Text
numberOfLines={1}
style={[
{
opacity,
transform: [
{
scale: opacity.interpolate({
inputRange: [0, 1],
outputRange: [0.5, 1],
}),
},
],
borderColor,
backgroundColor,
color: textColor,
fontSize,
lineHeight,
minWidth,
height: size,
borderRadius,
},
styles.container,
additionalStyle,
restStyle,
]}
testID={testID}
{...rest}
>
{badge}
</Animated.Text>
);
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: -1,
left: 15,
alignSelf: 'flex-end',
textAlign: 'center',
paddingHorizontal: 4,
overflow: 'hidden',
borderWidth: 2,
fontFamily: 'OpenSans-Bold',
},
});