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} />} + + )} ); };