Skip to content

Commit 3497332

Browse files
committed
feat(notifications): Add new NotificationsPanel component
This code add the new NotificationsPanel component within the notifications scope and drop the usage of standard dropdown on AlertsDropdown using the new component. Besides, the NotificationsPanel is powered by popperjs on its react version to avoid extra code to calculate position of the component and handle overflows cases easier
1 parent 64dff55 commit 3497332

6 files changed

Lines changed: 116 additions & 48 deletions

File tree

__mocks__/popper.js.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import PopperJs from "popper.js";
2+
3+
export default class Popper {
4+
static placements = PopperJs.placements;
5+
6+
constructor() {
7+
return {
8+
destroy: () => {},
9+
scheduleUpdate: () => {},
10+
};
11+
}
12+
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
"@material-ui/core": "^3.9.0",
77
"@material-ui/icons": "^3.0.2",
88
"lodash": "^4.17.11",
9+
"moment": "^2.24.0",
910
"react": "^16.7.0",
1011
"react-dom": "^16.7.0",
12+
"react-popper": "^1.3.3",
1113
"react-scripts": "2.1.8",
1214
"styled-components": "^4.1.3"
1315
},
Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
11
// @flow
22

33
import { getNotificationIcon } from "./helpers";
4+
import moment from "moment";
45
import { NotificationsPanelComponents as NPC } from "./styled";
56
import React from "react";
67
import { Typography } from "@material-ui/core";
78

8-
export const NotificationsPanel = ({
9-
notifications,
10-
}: {
9+
type Props = {
10+
handleClose: Function,
1111
notifications: Array<Notification>,
12-
}) => {
12+
};
13+
14+
export const NotificationsPanel = ({ handleClose, notifications }: Props) => {
1315
return (
1416
<NPC.Container>
1517
<NPC.Header>
1618
<Typography variant="caption">Notifications</Typography>
1719
</NPC.Header>
1820
<NPC.Body>
1921
{notifications.map(n => (
20-
<NPC.Item key={n.id}>
22+
<NPC.Item key={n.created_at} onClick={handleClose}>
2123
{getNotificationIcon("foo")}
2224
<div>
23-
<Typography variant="body2">
24-
Achievement completed! <strong>Know your stuff I</strong>
25+
<Typography variant="body2">{n.data.topic_title}</Typography>
26+
<Typography variant="caption">
27+
{moment(n.created_at).fromNow()}
2528
</Typography>
26-
<Typography variant="caption">1 hour ago</Typography>
2729
</div>
2830
</NPC.Item>
2931
))}
@@ -32,3 +34,5 @@ export const NotificationsPanel = ({
3234
</NPC.Container>
3335
);
3436
};
37+
38+
NotificationsPanel.Caret = NPC.Caret;

src/notifications/styled.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,29 @@ const NotificationsPanelContainer = styled.div`
1818
width: 25rem;
1919
`;
2020

21+
const NotificationsPanelCaret = styled.div`
22+
background: ${grey[100]}
23+
border: 1px solid ${grey[400]};
24+
border-bottom-color: transparent;
25+
border-left-color: transparent;
26+
display: block;
27+
height: 0.6rem;
28+
position: relative;
29+
top: 0.4rem;
30+
transform: rotate(-45deg);
31+
width: 0.6rem;
32+
z-index: 1;
33+
`;
34+
2135
const NotificationsPanelFooter = styled.div`
36+
background: ${grey[100]}
2237
border-top: 1px solid ${grey[400]};
2338
height: 2.125rem;
2439
`;
2540

2641
const NotificationsPanelHeader = styled.div`
2742
align-items: center;
43+
background: ${grey[100]}
2844
border-bottom: 1px solid ${grey[400]};
2945
display: flex;
3046
height: 2.125rem;
@@ -52,6 +68,7 @@ const NotificationsPanelItem = styled.div`
5268

5369
export const NotificationsPanelComponents = {
5470
Body: NotificationsPanelBody,
71+
Caret: NotificationsPanelCaret,
5572
Container: NotificationsPanelContainer,
5673
Footer: NotificationsPanelFooter,
5774
Header: NotificationsPanelHeader,

src/profile/AlertsDropdown.js

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,56 @@
33
import Badge from "@material-ui/core/Badge";
44
import IconButton from "@material-ui/core/IconButton";
55
import NotificationsIcon from "@material-ui/icons/Notifications";
6-
import { Menu, MenuItem, Typography } from "@material-ui/core";
6+
import { NotificationsPanel } from "../notifications";
7+
import { Manager, Popper, Reference } from "react-popper";
78
import React, { useState } from "react";
89

910
const DROPDOWN_NAME = "@@profile/alerts/dropdown";
1011

11-
const Dropdown = ({ anchorEl, handleClose, alerts }) => (
12-
<Menu
13-
id={DROPDOWN_NAME}
14-
anchorEl={anchorEl}
15-
open={Boolean(anchorEl)}
16-
onClose={handleClose}
17-
>
18-
{alerts.map(alert => (
19-
<MenuItem
20-
component="a"
21-
href={alert.data.original_post_id}
22-
key={alert.created_at}
23-
onClick={handleClose}
24-
>
25-
<Typography color="primary" variant="subtitle1">
26-
{alert.data.topic_title}
27-
</Typography>
28-
</MenuItem>
29-
))}
30-
</Menu>
31-
);
32-
3312
export const AlertsDropdown = ({ alerts }: { alerts: Array<Alert> }) => {
3413
const [anchorEl, setAnchorEl] = useState(null);
3514
const handleClose = () => setAnchorEl(null);
36-
const toggle = e => setAnchorEl(e.currentTarget);
15+
const toggle = e => (anchorEl ? handleClose() : setAnchorEl(e.currentTarget));
3716

3817
return (
39-
<React.Fragment>
40-
<IconButton
41-
aria-label="AlertsToggler"
42-
color="inherit"
43-
aria-owns={anchorEl ? DROPDOWN_NAME : undefined}
44-
aria-haspopup="true"
45-
onClick={toggle}
46-
>
47-
<Badge badgeContent={alerts.length} color="secondary">
48-
<NotificationsIcon />
49-
</Badge>
50-
</IconButton>
51-
<Dropdown anchorEl={anchorEl} handleClose={handleClose} alerts={alerts} />
52-
</React.Fragment>
18+
<Manager>
19+
<Reference>
20+
{({ ref }) => (
21+
<span ref={ref}>
22+
<IconButton
23+
aria-label="AlertsToggler"
24+
color="inherit"
25+
aria-owns={anchorEl ? DROPDOWN_NAME : undefined}
26+
aria-haspopup="true"
27+
onClick={toggle}
28+
>
29+
<Badge badgeContent={alerts.length} color="secondary">
30+
<NotificationsIcon />
31+
</Badge>
32+
</IconButton>
33+
</span>
34+
)}
35+
</Reference>
36+
<Popper placement="bottom-end">
37+
{({ ref, style, placement, arrowProps }) => (
38+
<div
39+
ref={ref}
40+
style={{
41+
...style,
42+
margin: 2,
43+
visibility: anchorEl ? "visible" : "hidden",
44+
}}
45+
data-placement={placement}
46+
>
47+
<NotificationsPanel.Caret
48+
ref={arrowProps.ref}
49+
style={arrowProps.style}
50+
/>
51+
<NotificationsPanel notifications={alerts} />
52+
</div>
53+
)}
54+
</Popper>
55+
</Manager>
5356
);
5457
};
5558

yarn.lock

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4011,6 +4011,14 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
40114011
safe-buffer "^5.0.1"
40124012
sha.js "^2.4.8"
40134013

4014+
create-react-context@<=0.2.2:
4015+
version "0.2.2"
4016+
resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.2.tgz#9836542f9aaa22868cd7d4a6f82667df38019dca"
4017+
integrity sha512-KkpaLARMhsTsgp0d2NA/R94F/eDLbhXERdIq3LvX2biCAXcDvHYoOqHfWCHf1+OLj+HKBotLG3KqaOOf+C1C+A==
4018+
dependencies:
4019+
fbjs "^0.8.0"
4020+
gud "^1.0.0"
4021+
40144022
create-react-context@^0.2.3:
40154023
version "0.2.3"
40164024
resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3"
@@ -9515,6 +9523,11 @@ modify-values@^1.0.0:
95159523
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
95169524
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
95179525

9526+
moment@^2.24.0:
9527+
version "2.24.0"
9528+
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
9529+
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
9530+
95189531
move-concurrently@^1.0.1:
95199532
version "1.0.1"
95209533
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@@ -10804,7 +10817,7 @@ polished@^2.3.1:
1080410817
dependencies:
1080510818
"@babel/runtime" "^7.2.0"
1080610819

10807-
popper.js@^1.14.1:
10820+
popper.js@^1.14.1, popper.js@^1.14.4:
1080810821
version "1.14.7"
1080910822
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.7.tgz#e31ec06cfac6a97a53280c3e55e4e0c860e7738e"
1081010823
integrity sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ==
@@ -12081,6 +12094,18 @@ react-perfect-scrollbar@^1.4.2:
1208112094
perfect-scrollbar "^1.4.0"
1208212095
prop-types "^15.6.1"
1208312096

12097+
react-popper@^1.3.3:
12098+
version "1.3.3"
12099+
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-1.3.3.tgz#2c6cef7515a991256b4f0536cd4bdcb58a7b6af6"
12100+
integrity sha512-ynMZBPkXONPc5K4P5yFWgZx5JGAUIP3pGGLNs58cfAPgK67olx7fmLp+AdpZ0+GoQ+ieFDa/z4cdV6u7sioH6w==
12101+
dependencies:
12102+
"@babel/runtime" "^7.1.2"
12103+
create-react-context "<=0.2.2"
12104+
popper.js "^1.14.4"
12105+
prop-types "^15.6.1"
12106+
typed-styles "^0.0.7"
12107+
warning "^4.0.2"
12108+
1208412109
react-powerplug@^1.0.0:
1208512110
version "1.0.0"
1208612111
resolved "https://registry.yarnpkg.com/react-powerplug/-/react-powerplug-1.0.0.tgz#f9c10a761ece115661b8fd10920c4e573ea95909"
@@ -14351,6 +14376,11 @@ type-is@~1.6.16:
1435114376
media-typer "0.3.0"
1435214377
mime-types "~2.1.18"
1435314378

14379+
typed-styles@^0.0.7:
14380+
version "0.0.7"
14381+
resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9"
14382+
integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==
14383+
1435414384
typedarray@^0.0.6:
1435514385
version "0.0.6"
1435614386
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
@@ -14858,7 +14888,7 @@ warning@^3.0.0:
1485814888
dependencies:
1485914889
loose-envify "^1.0.0"
1486014890

14861-
warning@^4.0.1:
14891+
warning@^4.0.1, warning@^4.0.2:
1486214892
version "4.0.3"
1486314893
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
1486414894
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==

0 commit comments

Comments
 (0)