diff --git a/.changeset/easy-bottles-type.md b/.changeset/easy-bottles-type.md
new file mode 100644
index 0000000000..a2b131d7b5
--- /dev/null
+++ b/.changeset/easy-bottles-type.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-notifications': patch
+---
+
+Added `renderItem` prop to `NotificationsSidebarItem` component, allowing custom UI rendering while retaining all built-in notification logic (unread count, snackbar, signals, web notifications).
diff --git a/plugins/notifications/report.api.md b/plugins/notifications/report.api.md
index 0d2912638f..8a1fd47bad 100644
--- a/plugins/notifications/report.api.md
+++ b/plugins/notifications/report.api.md
@@ -141,6 +141,13 @@ export const notificationsPlugin: BackstagePlugin<
{}
>;
+// @public
+export type NotificationsRenderItemProps = {
+ unreadCount: number;
+ to: string;
+ onClick: () => void;
+};
+
// @public (undocumented)
export const NotificationsSidebarItem: (
props?: NotificationsSideBarItemProps,
@@ -158,6 +165,7 @@ export type NotificationsSideBarItemProps = {
text?: string;
disableHighlight?: boolean;
noTrack?: boolean;
+ renderItem?: (props: NotificationsRenderItemProps) => React.ReactNode;
};
// @public (undocumented)
diff --git a/plugins/notifications/src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx b/plugins/notifications/src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx
index 53e04494c1..70407d8e8d 100644
--- a/plugins/notifications/src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx
+++ b/plugins/notifications/src/components/NotificationsSideBarItem/NotificationsSideBarItem.tsx
@@ -99,6 +99,19 @@ export type NotificationSnackbarProperties = {
};
};
+/**
+ * Props passed to the custom renderItem function
+ * @public
+ */
+export type NotificationsRenderItemProps = {
+ /** Current unread notification count */
+ unreadCount: number;
+ /** Route path to the notifications page */
+ to: string;
+ /** Click handler that requests web notification permission */
+ onClick: () => void;
+};
+
/**
* @public
*/
@@ -119,6 +132,10 @@ export type NotificationsSideBarItemProps = {
text?: string;
disableHighlight?: boolean;
noTrack?: boolean;
+ /**
+ * Optional render function to provide custom UI instead of the default SidebarItem.
+ */
+ renderItem?: (props: NotificationsRenderItemProps) => React.ReactNode;
};
/** @public */
@@ -304,6 +321,20 @@ export const NotificationsSidebarItem = (
const count = !error && !!unreadCount ? unreadCount : undefined;
+ const handleClick = useCallback(() => {
+ requestUserPermission();
+ }, [requestUserPermission]);
+
+ // Props to pass to custom renderItem function
+ const renderItemProps: NotificationsRenderItemProps = useMemo(
+ () => ({
+ unreadCount,
+ to: notificationsRoute,
+ onClick: handleClick,
+ }),
+ [unreadCount, notificationsRoute, handleClick],
+ );
+
return (
<>
{snackbarEnabled && (
@@ -336,17 +367,19 @@ export const NotificationsSidebarItem = (
}}
/>
)}
- {
- requestUserPermission();
- }}
- text={text}
- icon={icon}
- {...restProps}
- >
- {count && 99 ? '99+' : count} />}
-
+ {props?.renderItem ? (
+ props.renderItem(renderItemProps)
+ ) : (
+
+ {count && 99 ? '99+' : count} />}
+
+ )}
>
);
};