ionian/src/client/page/headline.tsx
2021-02-22 23:07:20 +09:00

209 lines
No EOL
6.9 KiB
TypeScript

import ReactDom from 'react-dom';
import React, { useState } from 'react';
import {
Button, CssBaseline, Divider, IconButton, List, ListItem, Drawer,
AppBar, Toolbar, Typography, InputBase, ListItemIcon, ListItemText, Menu, MenuItem,
Hidden, Tooltip
} from '@material-ui/core';
import { makeStyles, Theme, useTheme, fade } from '@material-ui/core/styles';
import { ChevronLeft, ChevronRight, Menu as MenuIcon, Search as SearchIcon, ArrowBack as ArrowBackIcon, AccountCircle } from '@material-ui/icons';
import {Link} from 'react-router-dom';
const drawerWidth = 240;
const useStyles = makeStyles((theme: Theme) => ({
root: {
display: 'flex'
},
appBar: {
zIndex: theme.zIndex.drawer + 1,
transition: theme.transitions.create(['width', 'margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen
})
},
menuButton: {
marginRight: 36
},
hide: {
display: "none"
},
drawer: {
flexShrink: 0,
whiteSpace: "nowrap",
[theme.breakpoints.up("sm")]:{
width: drawerWidth,
},
},
drawerPaper: {
width: drawerWidth
},
drawerClose: {
overflowX: 'hidden',
[theme.breakpoints.up("sm")]:{
width: theme.spacing(7) + 1,
},
},
toolbar: {
...theme.mixins.toolbar,
},
content: {
display:'flex',
flexFlow: 'column',
flexGrow: 1,
padding: theme.spacing(3),
},
title: {
display: 'none',
[theme.breakpoints.up("sm")]: {
display: 'block'
}
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
width: 'auto',
},
},
searchIcon: {
padding: theme.spacing(0, 2),
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
inputRoot: {
color: 'inherit'
},
inputInput: {
padding: theme.spacing(1, 1, 1, 0),
// vertical padding + font size from searchIcon
paddingLeft: `calc(1em + ${theme.spacing(4)}px)`,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('md')]: {
width: '20ch',
"&:hover": {
width: '25ch'
}
},
},
grow: {
flexGrow: 1,
},
}));
export const Headline = (prop: { children?: React.ReactNode, navListItem?: React.ReactNode, isLogin?:boolean}) => {
const [v, setv] = useState(false);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const classes = useStyles();
const theme = useTheme();
const toggleV = () => setv(!v);
const handleProfileMenuOpen = (e:React.MouseEvent<HTMLElement>)=>setAnchorEl(e.currentTarget);
const handleProfileMenuClose = ()=>setAnchorEl(null);
const isProfileMenuOpened = Boolean(anchorEl);
const menuId = 'primary-search-account-menu';
const isLogin = prop.isLogin || false;
const renderProfileMenu = (<Menu
anchorEl={anchorEl}
anchorOrigin={{horizontal:'right',vertical:"top"}}
id={menuId}
open={isProfileMenuOpened}
keepMounted
transformOrigin={{horizontal:'right',vertical:"top"}}
onClose={handleProfileMenuClose}
>
<MenuItem component={Link} to='/profile'>Profile</MenuItem>
<MenuItem>Logout</MenuItem>
</Menu>);
const drawer_contents = (<>
<div className={classes.toolbar}>
<IconButton onClick={toggleV}>
{theme.direction === "ltr" ? <ChevronLeft /> : <ChevronRight />}
</IconButton>
</div>
<Divider />
<List>
<ListItem button key="Back">
<ListItemIcon>
<Tooltip title="back" placement="bottom">
<ArrowBackIcon></ArrowBackIcon>
</Tooltip>
</ListItemIcon>
<ListItemText primary="Back"></ListItemText>
</ListItem>
{prop.navListItem}
</List>
</>);
return (<div className={classes.root}>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<IconButton color="inherit"
aria-label="open drawer"
onClick={toggleV}
edge="start"
className={classes.menuButton}>
<MenuIcon></MenuIcon>
</IconButton>
<Typography variant="h5" noWrap className={classes.title}>
Ionian
</Typography>
<div className={classes.grow}></div>
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase placeholder="search"
classes={{ root: classes.inputRoot, input: classes.inputInput }}></InputBase>
</div>
{
isLogin ?
<IconButton
edge="end"
aria-label="account of current user"
aria-controls={menuId}
aria-haspopup="true"
onClick={handleProfileMenuOpen}
color="inherit">
<AccountCircle />
</IconButton>
: <Button color="inherit">Login</Button>
}
</Toolbar>
</AppBar>
{renderProfileMenu}
<nav>
<Hidden smUp implementation="css">
<Drawer variant="temporary" anchor='left' open={v} onClose={toggleV}
classes={{paper: classes.drawerPaper}}>
{drawer_contents}
</Drawer>
</Hidden>
<Hidden xsDown implementation="css">
<Drawer variant='permanent' anchor='left' className={[classes.drawer, classes.drawerClose].join(" ").trim()} classes={{
paper: classes.drawerClose
}}>
{drawer_contents}
</Drawer>
</Hidden>
</nav>
<main className={classes.content}>
<div className={classes.toolbar}></div>
{prop.children}
</main>
</div>);
};
export default Headline;