-
Notifications
You must be signed in to change notification settings - Fork 2.9k
/
Banner.tsx
134 lines (118 loc) · 4.8 KB
/
Banner.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import React, {memo} from 'react';
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
import {View} from 'react-native';
import useLocalize from '@hooks/useLocalize';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import getButtonState from '@libs/getButtonState';
import CONST from '@src/CONST';
import type IconAsset from '@src/types/utils/IconAsset';
import Hoverable from './Hoverable';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
import PressableWithFeedback from './Pressable/PressableWithFeedback';
import RenderHTML from './RenderHTML';
import Text from './Text';
import Tooltip from './Tooltip';
type BannerProps = {
/** Text to display in the banner. */
text?: string;
/** Content to display in the banner. */
content?: React.ReactNode;
/** The icon asset to display to the left of the text */
icon?: IconAsset | null;
/** Should this component render the left-aligned exclamation icon? */
shouldShowIcon?: boolean;
/** Should this component render a close button? */
shouldShowCloseButton?: boolean;
/** Should this component render the text as HTML? */
shouldRenderHTML?: boolean;
/** Callback called when the close button is pressed */
onClose?: () => void;
/** Callback called when the message is pressed */
onPress?: () => void;
/** Styles to be assigned to the Banner container */
containerStyles?: StyleProp<ViewStyle>;
/** Styles to be assigned to the Banner text */
textStyles?: StyleProp<TextStyle>;
};
function Banner({
text,
content,
icon = Expensicons.Exclamation,
onClose,
onPress,
containerStyles,
textStyles,
shouldRenderHTML = false,
shouldShowIcon = false,
shouldShowCloseButton = false,
}: BannerProps) {
const theme = useTheme();
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {translate} = useLocalize();
return (
<Hoverable>
{(isHovered) => {
const isClickable = onClose ?? onPress;
const shouldHighlight = isClickable && isHovered;
return (
<View
style={[
styles.flexRow,
styles.alignItemsCenter,
styles.p5,
styles.borderRadiusNormal,
shouldHighlight ? styles.activeComponentBG : styles.hoveredComponentBG,
styles.breakAll,
containerStyles,
]}
>
<View style={[styles.flexRow, styles.flex1, styles.mw100, styles.alignItemsCenter]}>
{shouldShowIcon && !!icon && (
<View style={[styles.mr3]}>
<Icon
src={icon}
fill={StyleUtils.getIconFillColor(getButtonState(shouldHighlight))}
/>
</View>
)}
{content && content}
{text &&
(shouldRenderHTML ? (
<RenderHTML html={text} />
) : (
<Text
style={[styles.flex1, styles.flexWrap, textStyles]}
onPress={onPress}
suppressHighlighting
>
{text}
</Text>
))}
</View>
{shouldShowCloseButton && !!onClose && (
<Tooltip text={translate('common.close')}>
<PressableWithFeedback
onPress={onClose}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.close')}
>
<Icon
src={Expensicons.Close}
fill={theme.icon}
/>
</PressableWithFeedback>
</Tooltip>
)}
</View>
);
}}
</Hoverable>
);
}
Banner.displayName = 'Banner';
export default memo(Banner);
export type {BannerProps};