VisorVisor
Patterns

Notification Center

A popover-based notification hub with a command palette for filtering and bulk-managing alerts, toasts, and system messages.

Preview

When to Use

  • Apps with persistent in-app notifications or activity alerts
  • When users need to review, dismiss, or act on multiple notifications at once
  • Combining real-time toast feedback with a browsable notification history

Components Used

Structure

<Popover open={open} onOpenChange={setOpen}>
  <PopoverTrigger asChild>
    <Button variant="ghost" size="icon" aria-label="Notifications">
      <BellIcon />
      {unreadCount > 0 && (
        <Badge variant="destructive" className="notification-badge">
          {unreadCount}
        </Badge>
      )}
    </Button>
  </PopoverTrigger>
  <PopoverContent className="notification-popover">
    <Command>
      <CommandInput placeholder="Search notifications..." />
      <CommandList>
        <CommandGroup heading="Recent">
          <ScrollArea style={{ height: "320px" }}>
            {notifications.map((n) => (
              <CommandItem key={n.id} onSelect={() => handleSelect(n)}>
                <div className="notification-item">
                  <Badge variant={n.type === "error" ? "destructive" : "secondary"}>
                    {n.type}
                  </Badge>
                  <span>{n.message}</span>
                  <span className="notification-time">{n.timestamp}</span>
                </div>
              </CommandItem>
            ))}
          </ScrollArea>
        </CommandGroup>
        <CommandSeparator />
        <CommandGroup>
          <CommandItem onSelect={markAllRead}>Mark all as read</CommandItem>
          <CommandItem onSelect={clearAll}>Clear all</CommandItem>
        </CommandGroup>
      </CommandList>
    </Command>
  </PopoverContent>
</Popover>

Notes

  • Use ScrollArea inside CommandList to keep the popover height bounded.
  • Pair with useToast for real-time feedback on actions taken within the center.
  • Badge on the trigger should disappear when unreadCount reaches zero.
  • For high-volume systems, paginate or virtualize the notification list rather than loading all at once.