diff options
author | Eugene Sokolov <eug-vs@keemail.me> | 2020-08-11 23:17:28 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-11 23:17:28 +0300 |
commit | 94067ef2a0d9ac5c2aa5f45eca5366a2251ac04a (patch) | |
tree | 51e502c7d1be7c8ad2179daf2f5c9bfd27911636 /src | |
parent | c6723fa8a2a303f356b1756b45b2190203c96582 (diff) | |
parent | b5ce9be31993f5b4bee9abbe57d775b7ea407507 (diff) | |
download | which-ui-94067ef2a0d9ac5c2aa5f45eca5366a2251ac04a.tar.gz |
Merge pull request #76 from which-ecosystem/redesign
Initial header redesign
Diffstat (limited to 'src')
-rw-r--r-- | src/components/Avatar/Avatar.tsx | 36 | ||||
-rw-r--r-- | src/components/Header/BottomBar.tsx | 39 | ||||
-rw-r--r-- | src/components/Header/BrowserHeader.tsx | 51 | ||||
-rw-r--r-- | src/components/Header/Header.tsx | 103 | ||||
-rw-r--r-- | src/components/Header/MobileHeader.tsx | 43 | ||||
-rw-r--r-- | src/components/UserStrip/UserStrip.tsx | 26 | ||||
-rw-r--r-- | src/containers/Page/Page.tsx | 2 | ||||
-rw-r--r-- | src/containers/Profile/ProfileInfo.tsx | 11 |
8 files changed, 228 insertions, 83 deletions
diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx new file mode 100644 index 0000000..e445891 --- /dev/null +++ b/src/components/Avatar/Avatar.tsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { Avatar as AvatarBase } from '@material-ui/core'; +import AccountCircle from '@material-ui/icons/AccountCircle'; +import { User } from 'which-types'; + +interface PropTypes { + user: User; + className?: string; +} + +const Avatar: React.FC<PropTypes> = ({ user, className }) => { + const history = useHistory(); + const { username, avatarUrl } = user; + + const handleClick = () => { + history.push(`/profile/${username}`); + }; + + return avatarUrl ? ( + <AvatarBase + src={avatarUrl} + alt={username[0].toUpperCase()} + onClick={handleClick} + className={className} + style={{ cursor: 'pointer' }} + /> + ) : ( + <AccountCircle + className={className} + onClick={handleClick} + /> + ); +}; + +export default Avatar; diff --git a/src/components/Header/BottomBar.tsx b/src/components/Header/BottomBar.tsx new file mode 100644 index 0000000..67fe219 --- /dev/null +++ b/src/components/Header/BottomBar.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { AppBar, Toolbar } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; + +interface PropTypes { + profile: JSX.Element; + feed: JSX.Element; + notifications: JSX.Element; +} + +const useStyles = makeStyles({ + root: { + top: 'auto', + bottom: 0 + }, + toolbar: { + display: 'flex', + justifyContent: 'space-around' + } +}); + + +const BottomBar: React.FC<PropTypes> = React.memo(props => { + const classes = useStyles(); + const { profile, feed, notifications } = props; + + return ( + <AppBar position="fixed" className={classes.root}> + <Toolbar className={classes.toolbar}> + {notifications} + {feed} + {profile} + </Toolbar> + </AppBar> + ); +}); + +export default BottomBar; + diff --git a/src/components/Header/BrowserHeader.tsx b/src/components/Header/BrowserHeader.tsx new file mode 100644 index 0000000..2dda717 --- /dev/null +++ b/src/components/Header/BrowserHeader.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { AppBar, Toolbar } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import SearchBar from './SearchBar'; + +interface PropTypes { + logo: JSX.Element; + feed: JSX.Element; + notifications: JSX.Element; + profile: JSX.Element; +} + +const useStyles = makeStyles({ + root: { + width: '60%', + margin: 'auto', + display: 'flex', + justifyContent: 'space-around' + }, + group: { + display: 'flex' + } +}); + + +const BrowserHeader: React.FC<PropTypes> = React.memo(props => { + const classes = useStyles(); + const { + logo, + feed, + notifications, + profile + } = props; + + return ( + <AppBar position="fixed"> + <Toolbar className={classes.root}> + {logo} + <SearchBar /> + <div className={classes.group}> + {feed} + {notifications} + {profile} + </div> + </Toolbar> + </AppBar> + ); +}); + +export default BrowserHeader; + diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index c3a678c..5621dbf 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -1,47 +1,38 @@ import React from 'react'; import { useHistory } from 'react-router-dom'; import { - AppBar, - Toolbar, IconButton, Typography, - Avatar, useMediaQuery } from '@material-ui/core'; +import { + AccountCircle, + Notifications, + Home, + Menu, + Search +} from '@material-ui/icons'; import { makeStyles, useTheme } from '@material-ui/core/styles'; -import AccountCircle from '@material-ui/icons/AccountCircle'; -import NotificationsIcon from '@material-ui/icons/Notifications'; -import HomeIcon from '@material-ui/icons/Home'; import { useAuth } from '../../hooks/useAuth'; -import SearchBar from './SearchBar'; +import MobileHeader from './MobileHeader'; +import BottomBar from './BottomBar'; +import BrowserHeader from './BrowserHeader'; +import Avatar from '../Avatar/Avatar'; const useStyles = makeStyles(theme => ({ - mobile: { - top: 'auto', - bottom: 0 - }, - toolbar: { - display: 'flex', - justifyContent: 'space-around' - }, - browserToolbar: { - width: '60%', - margin: 'auto' - }, logo: { fontWeight: 'bold', cursor: 'pointer', color: 'white' }, - round: { + avatar: { width: theme.spacing(3), height: theme.spacing(3) } })); - const Header: React.FC = React.memo(() => { const classes = useStyles(); const { user } = useAuth(); @@ -66,58 +57,54 @@ const Header: React.FC = React.memo(() => { history.push('/notifications'); }; - const FeedButton = ( + const feed = ( <IconButton onClick={handleFeed}> - <HomeIcon /> + <Home /> </IconButton> ); - const NotificationsButton = ( + const notifications = ( <IconButton onClick={handleNotifications}> - <NotificationsIcon /> + <Notifications /> </IconButton> ); - const ProfileButton = ( - <IconButton onClick={handleProfile}> - { - user?.avatarUrl - ? <Avatar className={classes.round} src={user?.avatarUrl} /> - : <AccountCircle /> - } + const menu = ( + <IconButton> + <Menu /> </IconButton> ); - const BrowserVersion = ( - <AppBar position="fixed"> - <Toolbar className={`${classes.toolbar} ${classes.browserToolbar}`}> - <Typography variant="h5" className={classes.logo} onClick={handleHome}> - Which - </Typography> - <SearchBar /> - <div> - {FeedButton} - {NotificationsButton} - {ProfileButton} - </div> - </Toolbar> - </AppBar> + const search = ( + <IconButton> + <Search /> + </IconButton> + ); + + const logo = ( + <Typography variant="h5" className={classes.logo} onClick={handleHome}> + Which + </Typography> ); - const MobileVersion = ( - <AppBar position="fixed" className={classes.mobile}> - <Toolbar className={classes.toolbar}> - <IconButton onClick={handleHome}> - <Typography className={`${classes.logo} ${classes.round}`}>W</Typography> - </IconButton> - {FeedButton} - {NotificationsButton} - {ProfileButton} - </Toolbar> - </AppBar> + const profile = ( + <IconButton onClick={handleProfile}> + { + user + ? <Avatar className={classes.avatar} user={user} /> + : <AccountCircle className={classes.avatar} /> + } + </IconButton> ); - return isMobile ? MobileVersion : BrowserVersion; + return isMobile ? ( + <> + <MobileHeader logo={logo} menu={menu} search={search} /> + <BottomBar feed={feed} profile={profile} notifications={notifications} /> + </> + ) : ( + <BrowserHeader logo={logo} profile={profile} notifications={notifications} feed={feed} /> + ); }); export default Header; diff --git a/src/components/Header/MobileHeader.tsx b/src/components/Header/MobileHeader.tsx new file mode 100644 index 0000000..a20d54a --- /dev/null +++ b/src/components/Header/MobileHeader.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { + AppBar, + Toolbar, + useScrollTrigger, + Slide +} from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; + +interface PropTypes { + menu: JSX.Element; + logo: JSX.Element; + search: JSX.Element; +} + +const useStyles = makeStyles({ + root: { + display: 'flex', + justifyContent: 'space-between' + } +}); + + +const MobileHeader: React.FC<PropTypes> = React.memo(props => { + const classes = useStyles(); + const trigger = useScrollTrigger(); + const { menu, search, logo } = props; + + return ( + <Slide appear={false} direction="down" in={!trigger}> + <AppBar position="fixed"> + <Toolbar className={classes.root}> + {menu} + {logo} + {search} + </Toolbar> + </AppBar> + </Slide> + ); +}); + +export default MobileHeader; + diff --git a/src/components/UserStrip/UserStrip.tsx b/src/components/UserStrip/UserStrip.tsx index 73d9363..a837961 100644 --- a/src/components/UserStrip/UserStrip.tsx +++ b/src/components/UserStrip/UserStrip.tsx @@ -1,10 +1,11 @@ import React from 'react'; -import { useHistory } from 'react-router-dom'; import { makeStyles } from '@material-ui/core/styles'; import VerifiedIcon from '@material-ui/icons/CheckCircleOutline'; -import { Avatar, CardHeader } from '@material-ui/core/'; +import { CardHeader } from '@material-ui/core/'; import { User } from 'which-types'; +import Avatar from '../Avatar/Avatar'; + interface PropTypes { user: User; @@ -21,30 +22,15 @@ const useStyles = makeStyles(theme => ({ marginLeft: theme.spacing(0.5), width: theme.spacing(2), height: theme.spacing(2) - }, - avatar: { - cursor: 'pointer' } })); const UserStrip: React.FC<PropTypes> = ({ user, info }) => { const classes = useStyles(); - const history = useHistory(); - const { username, avatarUrl, verified } = user; - - const handleNavigate = () => { - history.push(`/profile/${username}`); - }; - - const avatar = ( - <Avatar - src={avatarUrl} - alt={username[0].toUpperCase()} - onClick={handleNavigate} - className={classes.avatar} - /> - ); + const { username, verified } = user; + + const avatar = <Avatar user={user} />; const title = ( <div className={classes.root}> diff --git a/src/containers/Page/Page.tsx b/src/containers/Page/Page.tsx index 643e6de..f6a0aa5 100644 --- a/src/containers/Page/Page.tsx +++ b/src/containers/Page/Page.tsx @@ -16,7 +16,7 @@ const Notifications = React.lazy(() => import('../Notifications/Notifications')) const useStyles = makeStyles(theme => ({ root: { [theme.breakpoints.down('sm')]: { - margin: theme.spacing(2, 0, 12, 0) + margin: theme.spacing(15, 0, 12, 0) }, [theme.breakpoints.up('md')]: { margin: theme.spacing(15, 5, 8, 5) diff --git a/src/containers/Profile/ProfileInfo.tsx b/src/containers/Profile/ProfileInfo.tsx index 9eee4c1..a01c222 100644 --- a/src/containers/Profile/ProfileInfo.tsx +++ b/src/containers/Profile/ProfileInfo.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { Avatar, Badge, Typography } from '@material-ui/core/'; +import { Badge, Typography } from '@material-ui/core/'; import { makeStyles } from '@material-ui/core/styles'; import { User } from 'which-types'; import CameraAltIcon from '@material-ui/icons/CameraAlt'; @@ -8,9 +8,11 @@ import Skeleton from '@material-ui/lab/Skeleton'; import MoreMenu from './MoreMenu'; import Highlight from './Highlight'; import UploadImage from '../../components/UploadImage/UploadImage'; +import Avatar from '../../components/Avatar/Avatar'; import { patch } from '../../requests'; import { useAuth } from '../../hooks/useAuth'; + interface PropTypes { savedPolls: number; totalVotes: number; @@ -116,19 +118,20 @@ const ProfileInfo: React.FC<PropTypes> = ({ vertical: 'bottom', horizontal: 'right' }} + onClick={handleClick} badgeContent={( <div className={classes.badge}> - <CameraAltIcon onClick={handleClick} /> + <CameraAltIcon /> </div> )} > - <Avatar className={classes.avatar} src={userInfo?.avatarUrl} /> + <Avatar className={classes.avatar} user={userInfo} /> </Badge> </div> <UploadImage isOpen={input} setIsOpen={setInput} callback={patchAvatar} /> </div> ) - : <Avatar className={classes.avatar} src={userInfo?.avatarUrl} /> + : <Avatar className={classes.avatar} user={userInfo} /> } { !userInfo |