Portal Community

Bell States

3
3 unread notifications — red badge
Bell StateVisualMeaning
No notificationsBell icon, no badgeNo unread notifications
Has unread (normal)Bell + red badge with count (1-9)1-9 unread notifications
Has unread (many)Bell + red badge "9+"10 or more unread notifications
Has urgent unreadBell + red badge + pulsing animationAt least one urgent notification unread

Clicking the Bell

Clicking the bell opens the notification dropdown panel directly below the bell in the top navigation. The panel shows the 10 most recent notifications. A "View All" link at the bottom navigates to the full Notification History page.

Keyboard Shortcut

Press Alt+N to open or close the notification dropdown from anywhere in WorkDesk.

Browser Toast Notifications

For high and urgent priority notifications, WorkDesk shows a browser toast in the bottom-right corner — even if the notification panel is not open. Toasts auto-dismiss after 8 seconds or when clicked.

// Toast notification system
function showToast(notification: Notification) {
  const toast = document.createElement('div');
  toast.className = `notification-toast priority-${notification.priority}`;
  toast.innerHTML = `
    <div class="toast-icon">${getTypeIcon(notification.type)}</div>
    <div class="toast-body">
      <strong>${notification.title}</strong>
      <p>${notification.body}</p>
    </div>
    <button class="toast-close">×</button>
  `;
  toast.addEventListener('click', () => {
    window.location.href = notification.linkedUrl;
    markRead(notification.id);
  });
  document.getElementById('toast-container')!.appendChild(toast);
  setTimeout(() => toast.remove(), 8000);
}

Badge Count Zustand Store

// notificationStore.ts
import { create } from 'zustand';

interface NotificationStore {
  notifications: Notification[];
  unreadCount: number;
  addNotification: (n: Notification) => void;
  incrementUnread: () => void;
  markRead: (id: string) => void;
  markAllRead: () => void;
}

export const useNotificationStore = create<NotificationStore>((set) => ({
  notifications: [],
  unreadCount: 0,
  addNotification: (n) => set((s) => ({
    notifications: [n, ...s.notifications],
    unreadCount: s.unreadCount + (n.isRead ? 0 : 1),
  })),
  incrementUnread: () => set((s) => ({ unreadCount: s.unreadCount + 1 })),
  markRead: (id) => set((s) => ({
    notifications: s.notifications.map(n => n.id === id ? {...n, isRead: true} : n),
    unreadCount: Math.max(0, s.unreadCount - 1),
  })),
  markAllRead: () => set((s) => ({
    notifications: s.notifications.map(n => ({...n, isRead: true})),
    unreadCount: 0,
  })),
}));