-
Notifications
You must be signed in to change notification settings - Fork 381
Expand file tree
/
Copy pathNotificationBadge.tsx
More file actions
96 lines (88 loc) · 3.33 KB
/
NotificationBadge.tsx
File metadata and controls
96 lines (88 loc) · 3.33 KB
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
import { useEffect, useState } from 'react';
import { Button, ButtonVariant, ButtonProps } from '../Button';
import AttentionBellIcon from '@patternfly/react-icons/dist/esm/icons/attention-bell-icon';
import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon';
import styles from '@patternfly/react-styles/css/components/Button/button';
import { css } from '@patternfly/react-styles';
export enum NotificationBadgeVariant {
read = 'read',
unread = 'unread',
attention = 'attention',
plain = 'plain'
}
export interface NotificationBadgeProps extends Omit<ButtonProps, 'variant'> {
/** Adds an accessible label to the notification badge. */
'aria-label'?: string;
/** Icon to display for attention variant. */
attentionIcon?: React.ReactNode;
/** Content rendered inside the notification badge. */
children?: React.ReactNode;
/** Additional classes added to the notification badge. */
className?: string;
/** A number displayed in the badge alongside the icon. */
count?: number;
/** Icon to display in the notification badge. */
icon?: React.ReactNode;
/** Flag for applying expanded styling and setting the aria-expanded attribute on the
* notification badge.
*/
isExpanded?: boolean;
/** Determines the variant of the notification badge. */
variant?: NotificationBadgeVariant | 'read' | 'unread' | 'attention' | 'plain';
/** Flag indicating whether the notification badge animation should be triggered. Each
* time this prop is true, the animation will be triggered a single time.
*/
shouldNotify?: boolean;
/** Callback for when the animation of the notification badge icon ends.
*/
onAnimationEnd?: (event: React.AnimationEvent<HTMLButtonElement>) => void;
}
export const NotificationBadge: React.FunctionComponent<NotificationBadgeProps> = ({
children,
variant = NotificationBadgeVariant.read,
count = 0,
attentionIcon = <AttentionBellIcon />,
icon = <BellIcon />,
className,
isExpanded = false,
shouldNotify = false,
onAnimationEnd,
...props
}: NotificationBadgeProps) => {
const [isAnimating, setIsAnimating] = useState(shouldNotify);
const hasCount = count > 0;
const hasChildren = children !== undefined;
const isAttention = variant === NotificationBadgeVariant.attention;
const isPlain = variant === NotificationBadgeVariant.plain;
const _buttonState = isPlain ? undefined : (variant as 'read' | 'unread' | 'attention');
const notificationIcon = isAttention ? attentionIcon : icon;
let notificationContent: React.ReactNode = null;
if (hasCount) {
notificationContent = count;
} else if (hasChildren) {
notificationContent = children;
}
const buttonClassName = isAnimating ? css(className, styles.modifiers.notify) : className;
useEffect(() => {
setIsAnimating(shouldNotify);
}, [shouldNotify]);
const handleAnimationEnd = (event: React.AnimationEvent<HTMLButtonElement>) => {
onAnimationEnd?.(event);
setIsAnimating(false);
};
return (
<Button
variant={isPlain ? ButtonVariant.plain : ButtonVariant.stateful}
className={buttonClassName}
aria-expanded={isExpanded}
state={_buttonState}
isClicked={isExpanded}
icon={notificationIcon}
onAnimationEnd={handleAnimationEnd}
{...props}
>
{notificationContent}
</Button>
);
};
NotificationBadge.displayName = 'NotificationBadge';