fix: notification items are now real links (#2039)

Replace UnstyledButton with UnstyledButton component={Link} so each
notification renders as a real anchor element. Regular left-clicks use
SPA navigation and close the popover; Ctrl/Cmd/middle-click open the
page in a new tab. All click types mark the notification as read.
This commit is contained in:
Julien Fontanet
2026-03-28 21:23:21 +01:00
committed by GitHub
parent 3829b6cbef
commit aa27d57624
2 changed files with 23 additions and 16 deletions
@@ -13,7 +13,7 @@ import {
import { CustomAvatar } from "@/components/ui/custom-avatar";
import { INotification } from "../types/notification.types";
import { Trans, useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
import { Link } from "react-router-dom";
import { useState } from "react";
import { useMarkReadMutation } from "../queries/notification-query";
import { buildPageUrl } from "@/features/page/page.utils";
@@ -30,7 +30,6 @@ export function NotificationItem({
onNavigate,
}: NotificationItemProps) {
const { t } = useTranslation();
const navigate = useNavigate();
const markRead = useMarkReadMutation();
const [hovered, setHovered] = useState(false);
@@ -55,32 +54,39 @@ export function NotificationItem({
}
};
const handleClick = () => {
if (notification.page && notification.space) {
if (isUnread) {
markRead.mutate([notification.id]);
}
navigate(
buildPageUrl(
const pageUrl =
notification.page && notification.space
? buildPageUrl(
notification.space.slug,
notification.page.slugId,
notification.page.title,
),
);
onNavigate();
)
: undefined;
const markReadIfNeeded = () => {
if (isUnread) {
markRead.mutate([notification.id]);
}
};
const handleClick = () => {
markReadIfNeeded();
onNavigate();
};
const handleMarkRead = (e: React.MouseEvent) => {
e.stopPropagation();
if (isUnread) {
markRead.mutate([notification.id]);
}
markReadIfNeeded();
};
return (
<UnstyledButton
component={Link}
to={pageUrl ?? ""}
onClick={handleClick}
// auxclick fires for all non-primary buttons; guard to middle-click only (button 1)
// so that right-click (button 2, context menu) does not mark as read
onAuxClick={(e: React.MouseEvent) => e.button === 1 && markReadIfNeeded()}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
w="100%"
@@ -1,4 +1,5 @@
.notificationItem {
display: block;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;