forked from StellarSplit/StellarSplit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNotificationBell.tsx
More file actions
60 lines (56 loc) · 2.06 KB
/
Copy pathNotificationBell.tsx
File metadata and controls
60 lines (56 loc) · 2.06 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
import { useRef, useEffect } from "react";
import { Link } from "react-router-dom";
import { Bell } from "lucide-react";
import { useDisclosure } from "../../hooks/useDisclosure";
import { useNotificationsStore, selectUnreadCount } from "../../store/notifications";
import { NotificationDropdown } from "./NotificationDropdown";
export function NotificationBell() {
const { isOpen, onToggle, onClose } = useDisclosure(false);
const hasHydrated = useNotificationsStore((state) => state.hasHydrated);
const unreadCount = useNotificationsStore(selectUnreadCount);
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
containerRef.current &&
!containerRef.current.contains(event.target as Node)
) {
onClose();
}
};
if (isOpen) {
document.addEventListener("click", handleClickOutside);
return () => document.removeEventListener("click", handleClickOutside);
}
}, [isOpen, onClose]);
const visibleCount = hasHydrated ? unreadCount : 0;
return (
<div className="relative" ref={containerRef}>
<Link
to="/notifications"
className="relative p-2 rounded-full text-theme hover:bg-surface focus:outline-none focus:ring-2 ring-theme"
onClick={(e) => {
e.preventDefault();
onToggle();
}}
aria-label={`Notifications${visibleCount > 0 ? `, ${visibleCount} unread` : ""}`}
aria-expanded={isOpen}
aria-haspopup="true"
data-testid="notification-bell"
>
<Bell className="w-5 h-5" />
{visibleCount > 0 && (
<span
className="absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] flex items-center justify-center rounded-full bg-accent text-white text-xs font-medium"
data-testid="notification-badge"
>
{visibleCount > 99 ? "99+" : visibleCount}
</span>
)}
</Link>
{isOpen && (
<NotificationDropdown onClose={onClose} maxItems={5} />
)}
</div>
);
}