Skip to content

Commit aca71c5

Browse files
authored
feat(Notification): add href to notification props (#335)
1 parent 70e8f7e commit aca71c5

File tree

5 files changed

+87
-29
lines changed

5 files changed

+87
-29
lines changed

src/components/Notification/Notification.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ $notificationSourceIconSize: 36px;
1111
border-radius: 4px;
1212
box-sizing: border-box;
1313
width: 100%;
14+
font: inherit;
15+
color: inherit;
16+
text-decoration: none;
1417

1518
&_active:hover {
1619
background: var(--g-color-base-simple-hover);
20+
cursor: pointer;
1721
}
1822

1923
&__right {

src/components/Notification/Notification.tsx

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ export const Notification = React.memo(function Notification(props: Props) {
2525
sourcePlacement = 'bottom',
2626
} = notification;
2727

28-
const modifiers: CnMods = {unread, theme, mobile, active: Boolean(notification.onClick)};
28+
const modifiers: CnMods = {
29+
unread,
30+
theme,
31+
mobile,
32+
active: Boolean(notification.onClick || notification.href),
33+
};
2934
const titleId = useUniqId();
3035

3136
const sourceIcon = source && renderSourceIcon(source, titleId);
@@ -73,14 +78,8 @@ export const Notification = React.memo(function Notification(props: Props) {
7378
)
7479
: null;
7580

76-
return (
77-
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
78-
<div
79-
className={b(modifiers, notification.className)}
80-
onMouseEnter={notification.onMouseEnter}
81-
onMouseLeave={notification.onMouseLeave}
82-
onClick={notification.onClick}
83-
>
81+
const notificationContent = (
82+
<React.Fragment>
8483
{sourceIcon ? <div className={b('left')}>{sourceIcon}</div> : null}
8584

8685
<Flex className={b('right')} justifyContent="space-between" gap={2} overflow="hidden">
@@ -99,6 +98,43 @@ export const Notification = React.memo(function Notification(props: Props) {
9998
{renderedBottomActions}
10099
</Flex>
101100
</Flex>
101+
</React.Fragment>
102+
);
103+
104+
if (notification.href) {
105+
const handleLinkClick: React.MouseEventHandler<HTMLAnchorElement> = (event) => {
106+
if (event.target instanceof Element && event.target.closest('button')) {
107+
event.preventDefault();
108+
return;
109+
}
110+
111+
notification.onClick?.(event);
112+
};
113+
114+
return (
115+
<a
116+
className={b(modifiers, notification.className)}
117+
onMouseEnter={notification.onMouseEnter}
118+
onMouseLeave={notification.onMouseLeave}
119+
onClick={handleLinkClick}
120+
href={notification.href}
121+
target={notification.target ?? '_blank'}
122+
rel="noreferrer"
123+
>
124+
{notificationContent}
125+
</a>
126+
);
127+
}
128+
129+
return (
130+
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
131+
<div
132+
className={b(modifiers, notification.className)}
133+
onMouseEnter={notification.onMouseEnter}
134+
onMouseLeave={notification.onMouseLeave}
135+
onClick={notification.onClick}
136+
>
137+
{notificationContent}
102138
</div>
103139
);
104140
});

src/components/Notification/definitions.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ export type NotificationProps = {
3939
bottomActions?: React.ReactNode;
4040
swipeActions?: NotificationSwipeActionsProps;
4141

42-
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
43-
onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
44-
onClick?: React.MouseEventHandler<HTMLDivElement>;
42+
onMouseEnter?: React.MouseEventHandler<HTMLElement>;
43+
onMouseLeave?: React.MouseEventHandler<HTMLElement>;
44+
onClick?: React.MouseEventHandler<HTMLElement>;
45+
href?: string;
46+
target?: React.HTMLAttributeAnchorTarget;
4547
};
4648

4749
export type NotificationActionProps = {

src/components/Notifications/README.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,22 +67,24 @@ For more code examples go to [Notifications.stories.tsx](https://github.com/grav
6767

6868
**NotificationProps** — notification's type:
6969

70-
| Property | Type | Required | Default | Description |
71-
| :------------ | :------------------------------ | :------: | :------ | :--------------------------------------------------------------- |
72-
| id | `string` | `true` | | Unique identifier (used in `key` for example) |
73-
| content | `ReactNode` | `true` | | Notification's content (what it's about) |
74-
| title | `ReactNode` | | | Notification's title (bold) |
75-
| formattedDate | `ReactNode` | | | Notification's creation date (already formatted) |
76-
| unread | `boolean` | | `false` | Is notification unread |
77-
| archived | `boolean` | | `false` | Is notification archived (invisible to the user) |
78-
| source | `NotificationSourceProps` | | | Notification's source (e.g. Cloud/Tracker/Console) |
79-
| theme | `NotificationTheme` | | | Notification's theme (e.g. warning/danger) |
80-
| className | `string` | | | Notification's `className` |
81-
| sideActions | `ReactNode` | | | Notification's actions on the right side |
82-
| bottomActions | `ReactNode` | | | Notification's bottom actions (as buttons by default) |
83-
| swipeActions | `NotificationSwipeActionsProps` | | | Notification's action on left/right swipe (mobile mode required) |
84-
| onMouseEnter | `MouseEventHandler` | | | Callback for `onMouseEnter` |
85-
| onMouseLeave | `MouseEventHandler` | | | Callback for `onMouseLeave` |
86-
| onClick | `MouseEventHandler` | | | Callback for `onClick` |
70+
| Property | Type | Required | Default | Description |
71+
| :------------ | :------------------------------ | :------: | :-------- | :--------------------------------------------------------------- |
72+
| id | `string` | `true` | | Unique identifier (used in `key` for example) |
73+
| content | `ReactNode` | `true` | | Notification's content (what it's about) |
74+
| title | `ReactNode` | | | Notification's title (bold) |
75+
| formattedDate | `ReactNode` | | | Notification's creation date (already formatted) |
76+
| unread | `boolean` | | `false` | Is notification unread |
77+
| archived | `boolean` | | `false` | Is notification archived (invisible to the user) |
78+
| source | `NotificationSourceProps` | | | Notification's source (e.g. Cloud/Tracker/Console) |
79+
| theme | `NotificationTheme` | | | Notification's theme (e.g. warning/danger) |
80+
| className | `string` | | | Notification's `className` |
81+
| sideActions | `ReactNode` | | | Notification's actions on the right side |
82+
| bottomActions | `ReactNode` | | | Notification's bottom actions (as buttons by default) |
83+
| swipeActions | `NotificationSwipeActionsProps` | | | Notification's action on left/right swipe (mobile mode required) |
84+
| onMouseEnter | `MouseEventHandler` | | | Callback for `onMouseEnter` |
85+
| onMouseLeave | `MouseEventHandler` | | | Callback for `onMouseLeave` |
86+
| onClick | `MouseEventHandler` | | | Callback for `onClick` |
87+
| href | `string` | | | Notification url |
88+
| target | `HTMLAttributeAnchorTarget` | | `__blank` | Notification link target |
8789

8890
For a more detailed info on types go to [Notifications' types](https://github.com/gravity-ui/components/blob/main/src/components/Notifications/definitions.ts) and [Notification' types](https://github.com/gravity-ui/components/blob/main/src/components/Notification/definitions.ts).

src/components/Notifications/__stories__/mockData.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,20 @@ export const mockNotifications: NotificationProps[] = [
139139
formattedDate: '28 seconds ago',
140140
swipeActions: notificationsMockSwipeActions,
141141
},
142+
{
143+
id: 'click',
144+
content: <i>Notification with onClick callback</i>,
145+
formattedDate: '29 seconds ago',
146+
swipeActions: notificationsMockSwipeActions,
147+
onClick: () => alert('notification clicked'),
148+
},
149+
{
150+
id: 'link',
151+
content: <i>Notification with href</i>,
152+
formattedDate: '29 seconds ago',
153+
swipeActions: notificationsMockSwipeActions,
154+
href: 'https://ya.ru',
155+
},
142156
{
143157
id: 'yandex',
144158
content: (

0 commit comments

Comments
 (0)