diff options
Diffstat (limited to 'src/components/ui/InfoBar.tsx')
-rw-r--r-- | src/components/ui/InfoBar.tsx | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/components/ui/InfoBar.tsx b/src/components/ui/InfoBar.tsx new file mode 100644 index 000000000..ef8f6ad6f --- /dev/null +++ b/src/components/ui/InfoBar.tsx | |||
@@ -0,0 +1,89 @@ | |||
1 | import { Component, MouseEventHandler, ReactNode } from 'react'; | ||
2 | import { observer } from 'mobx-react'; | ||
3 | import classnames from 'classnames'; | ||
4 | import Loader from 'react-loader'; | ||
5 | import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; | ||
6 | |||
7 | import { mdiClose } from '@mdi/js'; | ||
8 | import { noop } from 'lodash'; | ||
9 | import Appear from './effects/Appear'; | ||
10 | import Icon from './icon'; | ||
11 | |||
12 | const messages = defineMessages({ | ||
13 | hide: { | ||
14 | id: 'infobar.hide', | ||
15 | defaultMessage: 'Hide', | ||
16 | }, | ||
17 | }); | ||
18 | |||
19 | interface IProps extends WrappedComponentProps { | ||
20 | children: ReactNode; | ||
21 | onClick?: MouseEventHandler<HTMLButtonElement>; | ||
22 | type?: string; | ||
23 | className?: string; | ||
24 | ctaLabel?: string; | ||
25 | ctaLoading?: boolean; | ||
26 | position?: string; | ||
27 | sticky?: boolean; | ||
28 | onHide?: () => void; | ||
29 | } | ||
30 | |||
31 | @observer | ||
32 | class InfoBar extends Component<IProps> { | ||
33 | render() { | ||
34 | const { | ||
35 | children, | ||
36 | type = 'primary', | ||
37 | onClick = noop, | ||
38 | className = '', | ||
39 | ctaLabel = '', | ||
40 | ctaLoading = false, | ||
41 | position = 'bottom', | ||
42 | sticky = false, | ||
43 | onHide = noop, | ||
44 | intl, | ||
45 | } = this.props; | ||
46 | |||
47 | const transitionName = position === 'top' ? 'slideDown' : 'slideUp'; | ||
48 | |||
49 | return ( | ||
50 | <Appear | ||
51 | transitionName={transitionName} | ||
52 | className={classnames({ | ||
53 | 'info-bar': true, | ||
54 | [`info-bar--${type}`]: true, | ||
55 | [`info-bar--${position}`]: true, | ||
56 | [`${className}`]: true, | ||
57 | })} | ||
58 | > | ||
59 | <div className="info-bar__content"> | ||
60 | {children} | ||
61 | {ctaLabel && ( | ||
62 | <button type="button" className="info-bar__cta" onClick={onClick}> | ||
63 | <Loader | ||
64 | loaded={!ctaLoading} | ||
65 | lines={10} | ||
66 | scale={0.3} | ||
67 | color="#FFF" | ||
68 | component="span" | ||
69 | /> | ||
70 | {ctaLabel} | ||
71 | </button> | ||
72 | )} | ||
73 | </div> | ||
74 | {!sticky && ( | ||
75 | <button | ||
76 | type="button" | ||
77 | className="info-bar__close" | ||
78 | onClick={onHide} | ||
79 | aria-label={intl.formatMessage(messages.hide)} | ||
80 | > | ||
81 | <Icon icon={mdiClose} /> | ||
82 | </button> | ||
83 | )} | ||
84 | </Appear> | ||
85 | ); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | export default injectIntl(InfoBar); | ||