Skip to content

Commit

Permalink
Add notification button components (#302)
Browse files Browse the repository at this point in the history
* Add notification button components

* Fix popper positioning

* Add popper arrow and inner content

* Give dropdown box shadow

* Add mobile view

* Fix box shadow on arrow for dropdown panel

* Fix coloring of unread notifications text
  • Loading branch information
AndrewLester authored Mar 3, 2022
1 parent adbec6a commit edb2165
Show file tree
Hide file tree
Showing 9 changed files with 272 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const styles = theme => ({
notificationButtonStyle: {
minWidth: '0px !important',
},
});

export default styles;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const styles = theme => ({
buttonStyle: {
borderRadius: '30px',
padding: '5px 15px',
color: '#757575',
backgroundColor: '#E4E4E4',
outline: 'none',
border: 'none',
cursor: 'pointer',
fontSize: '15px',
},
selectedButtonStyle: {
backgroundColor: '#00B8C4',
color: 'white',
},
});

export default styles;
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const styles = theme => ({
popperContainerStyle: {
top: '56px !important',
},
popperArrowStyle: {
width: '50px',
height: '50px',
top: '-19px',
background: 'white',
position: 'absolute',
transform: 'scaleX(0.7) rotate(45deg)',
transformOrigin: 'center',
borderRadius: '200px 0px 1000px 0px',
zIndex: '2000',
},
});

export default styles;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const styles = theme => ({
popperContainerStyle: {
top: '48px !important',
},
popperStyle: {
backgroundColor: 'white',
zIndex: 20,
padding: '20px',
borderRadius: '20px',
boxShadow: '0px 4px 4px 0px rgb(0 0 0 / 25%)',
},
fullscreenPopperStyle: {
width: '100vw',
height: '100vh',
borderRadius: '0px',
},
panelHeaderStyle: {
display: 'flex',
flexFlow: 'row nowrap',
alignItems: 'center',
gap: '10px',
color: '#00B8C4',
},
panelHeaderTextStyle: {
margin: '0px',
marginRight: '30px',
fontWeight: '600',
},
panelSubheadingTextStyle: {
margin: '5px 0px',
fontWeight: '600',
color: '#00B8C4',
},
fullWidth: {
width: '100%',
},
});

export default styles;
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { useRef, useState } from 'react';
import NotificationPanel from '../notification_panel/NotificationPanel';
import NotificationsIcon from '@material-ui/icons/Notifications';
import CustomButton from '../button/Button';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import cn from 'classnames';
import styles from '../../assets/js/styles/components/notification_button/notificationButtonStyles';
import { makeStyles } from '@material-ui/core/styles';

const useStyles = makeStyles(styles);

const NotificationButton = ({ className }) => {
const classes = useStyles();
const [dropdownOpen, setDropdownOpen] = useState(false);
const buttonRef = useRef();

return (
<ClickAwayListener onClickAway={() => setDropdownOpen(false)}>
<div>
<CustomButton
className={cn(className, classes.notificationButtonStyle)}
variant="contained"
primaryButtonStyle
customButtonStyle
size="small"
onClick={() => setDropdownOpen(!dropdownOpen)}
ref={buttonRef}
>
<NotificationsIcon />
</CustomButton>
<NotificationPanel open={dropdownOpen} anchorEl={buttonRef} />
</div>
</ClickAwayListener>
);
};

export default NotificationButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from 'react';
import styles from '../../assets/js/styles/components/notification_panel/notificationPanelStyles';
import { makeStyles } from '@material-ui/core/styles';
import NotificationPanelButton from './NotificationPanelButton';
import cn from 'classnames';
import NotificationPanelPopper from './NotificationPanelPopper';
import { useMediaQuery } from '@material-ui/core';

const useStyles = makeStyles(styles);

const NOTIFICATION_VIEW_TYPE = {
ALL: 'ALL',
UNREAD: 'UNREAD',
};

const NotificationPanel = ({ open, anchorEl }) => {
const classes = useStyles();
const mediaQuery = useMediaQuery('(max-width: 600px)');
const [notificationViewType, setNotificationViewType] = useState(
NOTIFICATION_VIEW_TYPE.ALL,
);

const getAllNotificationView = () => {
const newNotificationsLength = 1;
const earlierNotificationsLength = 1;

return (
<div>
{newNotificationsLength > 0 && (
<h2 className={classes.panelSubheadingTextStyle}>New</h2>
)}
{earlierNotificationsLength > 0 && (
<h2 className={classes.panelSubheadingTextStyle}>Earlier</h2>
)}
</div>
);
};

const getUnreadNotificationView = () => (
<div style={{ color: 'black' }}>Unread notifications here...</div>
);

return (
<NotificationPanelPopper open={open} anchorEl={anchorEl}>
<div
className={cn(
classes.popperStyle,
mediaQuery ? classes.fullscreenPopperStyle : '',
)}
>
<div className={classes.panelHeaderStyle}>
<h1 className={classes.panelHeaderTextStyle}>Notifications</h1>
<NotificationPanelButton
selected={notificationViewType === NOTIFICATION_VIEW_TYPE.ALL}
onClick={() => setNotificationViewType(NOTIFICATION_VIEW_TYPE.ALL)}
>
All
</NotificationPanelButton>
<NotificationPanelButton
selected={notificationViewType === NOTIFICATION_VIEW_TYPE.UNREAD}
onClick={() =>
setNotificationViewType(NOTIFICATION_VIEW_TYPE.UNREAD)
}
>
Unread
</NotificationPanelButton>
</div>
{notificationViewType === NOTIFICATION_VIEW_TYPE.ALL
? getAllNotificationView()
: getUnreadNotificationView()}
</div>
</NotificationPanelPopper>
);
};

export default NotificationPanel;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';
import styles from '../../assets/js/styles/components/notification_panel/notificationPanelButtonStyles';
import { makeStyles } from '@material-ui/core/styles';
import cn from 'classnames';

const useStyles = makeStyles(styles);

const NotificationPanelButton = ({ selected, children, ...rest }) => {
const classNames = useStyles();

const selectedButtonClassName = selected
? classNames.selectedButtonStyle
: '';

return (
<button
className={cn(classNames.buttonStyle, selectedButtonClassName)}
{...rest}
>
{children}
</button>
);
};

export default NotificationPanelButton;
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useMediaQuery } from '@material-ui/core';
import React from 'react';
import Popper from '@material-ui/core/Popper';
import { makeStyles } from '@material-ui/core/styles';

import styles from '../../assets/js/styles/components/notification_panel/notificationPanelPopperStyles';

const useStyles = makeStyles(styles);

const modifiers = {
offset: {
enabled: true,
offset: '20px, 30px',
},
arrow: {
enabled: true,
},
};

const fullscreenModifiers = {};

const NotificationPanelPopper = ({ open, anchorEl, children }) => {
const classes = useStyles();
const mediaQuery = useMediaQuery('(max-width: 600px)');

return (
<Popper
open={open}
anchorEl={mediaQuery ? undefined : anchorEl.current}
disablePortal={!mediaQuery}
modifiers={mediaQuery ? fullscreenModifiers : modifiers}
placement="bottom-end"
className={mediaQuery ? classes.popperContainerStyle : ''}
>
{!mediaQuery && (
<div x-arrow="true" className={classes.popperArrowStyle}></div>
)}
{children}
</Popper>
);
};

export default NotificationPanelPopper;
14 changes: 9 additions & 5 deletions zubhub_frontend/zubhub/src/views/PageWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,17 @@ import styles from '../assets/js/styles/views/page_wrapper/pageWrapperStyles';
import commonStyles from '../assets/js/styles';

import languageMap from '../assets/js/languageMap.json';
import NotificationButton from '../components/notification_button/NotificationButton';

const useStyles = makeStyles(styles);
const useCommonStyles = makeStyles(commonStyles);

/**
* @function PageWrapper View
* @author Raymond Ndibe <[email protected]>
*
* @todo - describe function's signature
*/
* @function PageWrapper View
* @author Raymond Ndibe <[email protected]>
*
* @todo - describe function's signature
*/
function PageWrapper(props) {
const backToTopEl = React.useRef(null);
const classes = useStyles();
Expand Down Expand Up @@ -325,6 +326,9 @@ function PageWrapper(props) {
>
<SearchIcon />
</IconButton>
<NotificationButton
className={clsx(common_classes.marginRight1em)}
/>
<Avatar
className={classes.avatarStyle}
aria-label={`${props.auth.username}' Avatar`}
Expand Down

0 comments on commit edb2165

Please sign in to comment.