Files
bruno/packages/bruno-app/src/components/Notifications/NotificationsModal/index.js
prateek-bruno 6711ccdda2 feat: redesign notification modal (#8140)
* fix: test expect

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: maintain state for read and cleared notification ids

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* feat: revamp Notifications

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: break things into components and use events

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: icon + more padding

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* chore: use classnames

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* chore: remove redundancy

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* chore: make it pixel accurate

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: remove redundant useMemo

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: colors of notification modal

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: use color paletter + fix badge color

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: ensure semantics for notification icon

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: handle keyboard navigation for drawer items

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: colors, no notification view, etc

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: don't crash on color of badge that is invalid

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix: use hex color for type of notification
Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

* fix

* Apply suggestions from code review

Co-authored-by: Sid <siddharth@usebruno.com>

* fix: use parseToRgb instead of custom isHexColor check + add unit tests

Co-authored-by: Prateek Sunal
<41370460+prateekmedia@users.noreply.github.com>

* fix: pointer events getting swallowed by iframe, causing resize issue

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>

---------

Co-authored-by: Prateek Sunal <41370460+prateekmedia@users.noreply.github.com>
Co-authored-by: naman-bruno <naman@usebruno.com>
Co-authored-by: Sid <siddharth@usebruno.com>
2026-06-18 21:28:47 +05:30

90 lines
2.8 KiB
JavaScript

import { useRef } from 'react';
import classnames from 'classnames';
import { useDragResize } from 'hooks/useDragResize';
import { usePersistedState } from 'hooks/usePersistedState';
import Modal from 'components/Modal/index';
import Portal from 'components/Portal';
import StyledWrapper from './StyledWrapper';
import NotificationTabs from './NotificationTabs';
import NotificationList from './NotificationList';
import NotificationDetail from './NotificationDetail';
const DEFAULT_SIDEBAR_WIDTH = 260;
const SIDEBAR_MIN = 200;
// Reserved for the detail pane; caps the sidebar at ~420px in the 800px modal.
const DETAIL_MIN = 380;
const NotificationsModal = ({ notifications, onClose }) => {
const {
visibleNotifications,
listed,
unreadCount,
activeTab,
selectedNotification,
onTabChange,
onSelect,
onMarkAllRead,
onClearAll
} = notifications;
const containerRef = useRef(null);
const [sidebarWidth, setSidebarWidth] = usePersistedState({
key: 'notification-sidebar',
default: DEFAULT_SIDEBAR_WIDTH
});
const { dragging, dragWidth, dragbarProps } = useDragResize({
containerRef,
width: sidebarWidth,
onWidthChange: (w) => setSidebarWidth(w ?? DEFAULT_SIDEBAR_WIDTH),
minLeft: SIDEBAR_MIN,
minRight: DETAIL_MIN
});
const effectiveWidth = dragging ? dragWidth : sidebarWidth;
const isEmpty = visibleNotifications.length === 0;
return (
<Portal>
<Modal
size="md"
title="Notifications"
confirmText="Close"
handleConfirm={onClose}
handleCancel={onClose}
hideFooter={true}
disableCloseOnOutsideClick={true}
disableEscapeKey={true}
noPadding={true}
>
<StyledWrapper className={classnames('notifications-modal', { dragging })} ref={containerRef}>
<div className="notif-sidebar" style={{ width: effectiveWidth, flexBasis: effectiveWidth }}>
<NotificationTabs
activeTab={activeTab}
unreadCount={unreadCount}
onTabChange={onTabChange}
onMarkAllRead={onMarkAllRead}
onClearAll={onClearAll}
/>
<NotificationList items={listed} selectedId={selectedNotification?.id} onSelect={onSelect} />
</div>
<div
className={classnames('notif-resize-handle', { dragging })}
{...dragbarProps}
role="separator"
aria-orientation="vertical"
aria-label="Resize sidebar"
/>
{isEmpty ? (
<div className="notif-empty">
<div className="notif-empty-text">You are all caught up!</div>
</div>
) : (
<NotificationDetail notification={selectedNotification} />
)}
</StyledWrapper>
</Modal>
</Portal>
);
};
export default NotificationsModal;