[Improvement] Using material-ui drawer
This commit is contained in:
@@ -7,7 +7,10 @@ import { connect } from 'react-redux'
|
||||
import { push } from 'react-router-redux'
|
||||
import { getTranslate, getActiveLanguage } from 'react-localize-redux'
|
||||
import config from 'src/config'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { withStyles } from 'material-ui/styles'
|
||||
import Drawer from 'material-ui/Drawer'
|
||||
import Menu from 'material-ui/Menu'
|
||||
import { MenuList, MenuItem } from 'material-ui/Menu'
|
||||
import { ListItemIcon, ListItemText } from 'material-ui/List'
|
||||
@@ -18,6 +21,11 @@ import SvgFeedback from 'material-ui-icons/Feedback'
|
||||
import SvgSettings from 'material-ui-icons/Settings'
|
||||
import SvgAccountCircle from 'material-ui-icons/AccountCircle'
|
||||
import SvgPeople from 'material-ui-icons/People'
|
||||
import List from 'material-ui/List'
|
||||
import Typography from 'material-ui/Typography'
|
||||
import IconButton from 'material-ui/IconButton'
|
||||
import Hidden from 'material-ui/Hidden'
|
||||
import MenuIcon from 'material-ui-icons/Menu'
|
||||
|
||||
// - Import app components
|
||||
import Sidebar from 'components/sidebar'
|
||||
@@ -48,67 +56,115 @@ import {
|
||||
import { IHomeComponentProps } from './IHomeComponentProps'
|
||||
import { IHomeComponentState } from './IHomeComponentState'
|
||||
|
||||
const drawerWidth = 240
|
||||
const styles = (theme: any) => ({
|
||||
root: {
|
||||
width: '100%',
|
||||
marginTop: theme.spacing.unit * 3,
|
||||
zIndex: 1,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
appFrame: {
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
navIconHide: {
|
||||
[theme.breakpoints.up('md')]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
drawerHeader: theme.mixins.toolbar,
|
||||
drawerPaper: {
|
||||
width: drawerWidth,
|
||||
[theme.breakpoints.up('md')]: {
|
||||
width: drawerWidth,
|
||||
position: 'relative',
|
||||
height: '100%',
|
||||
},
|
||||
},
|
||||
drawerPaperLarge: {
|
||||
width: drawerWidth,
|
||||
[theme.breakpoints.up('md')]: {
|
||||
width: drawerWidth,
|
||||
height: '100%',
|
||||
},
|
||||
top: 70,
|
||||
backgroundColor: 'transparent',
|
||||
borderRight: 0
|
||||
},
|
||||
menu: {
|
||||
height: '100%',
|
||||
backgroundColor: '#EEEEEE'
|
||||
},
|
||||
content: {
|
||||
backgroundColor: 'transparent',
|
||||
width: '100%',
|
||||
flexGrow: 1,
|
||||
padding: theme.spacing.unit * 1,
|
||||
transition: theme.transitions.create('margin', {
|
||||
easing: theme.transitions.easing.sharp,
|
||||
duration: theme.transitions.duration.leavingScreen,
|
||||
}),
|
||||
height: 'calc(100% - 56px)',
|
||||
marginTop: 56,
|
||||
[theme.breakpoints.up('sm')]: {
|
||||
height: 'calc(100% - 64px)',
|
||||
marginTop: 64,
|
||||
},
|
||||
},
|
||||
'content-left': {
|
||||
marginLeft: 0,
|
||||
},
|
||||
'content-right': {
|
||||
marginRight: 0,
|
||||
},
|
||||
contentShift: {
|
||||
transition: theme.transitions.create('margin', {
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
duration: theme.transitions.duration.enteringScreen,
|
||||
}),
|
||||
},
|
||||
'contentShift-left': {
|
||||
marginLeft: 0,
|
||||
[theme.breakpoints.up('md')]: {
|
||||
marginLeft: drawerWidth
|
||||
}
|
||||
},
|
||||
'contentShift-right': {
|
||||
marginRight: 0,
|
||||
[theme.breakpoints.up('md')]: {
|
||||
marginRight: drawerWidth
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// - Create Home component class
|
||||
export class HomeComponent extends Component<IHomeComponentProps, IHomeComponentState> {
|
||||
|
||||
// Constructor
|
||||
constructor (props: IHomeComponentProps) {
|
||||
constructor(props: IHomeComponentProps) {
|
||||
super(props)
|
||||
|
||||
// Default state
|
||||
this.state = {
|
||||
sidebarOpen: () => _,
|
||||
sidebarStatus: true,
|
||||
sidebarOverlay: false
|
||||
drawerOpen: false
|
||||
}
|
||||
|
||||
// Binding function to `this`
|
||||
this.sidebar = this.sidebar.bind(this)
|
||||
this.sidebarStatus = this.sidebarStatus.bind(this)
|
||||
this.sidebarOverlay = this.sidebarOverlay.bind(this)
|
||||
this.handleCloseSidebar = this.handleCloseSidebar.bind(this)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* handle close sidebar
|
||||
* Handle drawer toggle
|
||||
*/
|
||||
handleCloseSidebar = () => {
|
||||
this.state.sidebarOpen!(false, 'overlay')
|
||||
handleDrawerToggle = () => {
|
||||
console.trace('toggle')
|
||||
this.setState({ drawerOpen: !this.state.drawerOpen })
|
||||
}
|
||||
|
||||
/**
|
||||
* Change sidebar overlay status
|
||||
* @param {boolean} status if is true, the sidebar is on overlay status
|
||||
*/
|
||||
sidebarOverlay = (status: boolean) => {
|
||||
this.setState({
|
||||
sidebarOverlay: status
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the function to change sidebar status
|
||||
* @param {boolean} open is a function callback to change sidebar status out of sidebar component
|
||||
*/
|
||||
sidebar = (open: (status: boolean, source: string) => void) => {
|
||||
|
||||
this.setState({
|
||||
sidebarOpen: open
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Change sidebar status if is open or not
|
||||
* @param {boolean} status is true, if the sidebar is open
|
||||
*/
|
||||
sidebarStatus = (status: boolean) => {
|
||||
this.setState({
|
||||
sidebarStatus: status
|
||||
})
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
componentWillMount() {
|
||||
const { global, clearData, loadData, authed, defaultDataEnable, isVerifide, goTo } = this.props
|
||||
if (!authed) {
|
||||
goTo!('/login')
|
||||
@@ -132,76 +188,106 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
|
||||
*
|
||||
* @memberof Home
|
||||
*/
|
||||
render () {
|
||||
render() {
|
||||
const HR = HomeRouter as any
|
||||
const { loaded, authed, loadDataStream, mergedPosts, hasMorePosts, showSendFeedback, translate } = this.props
|
||||
const { loaded, authed, loadDataStream, mergedPosts, hasMorePosts, showSendFeedback, translate, classes, theme } = this.props
|
||||
const {drawerOpen} = this.state
|
||||
const drawer = (
|
||||
<>
|
||||
|
||||
<NavLink to='/'>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgHome />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.home')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<NavLink to={`/${this.props.uid}`}>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgAccountCircle />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.profile')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<NavLink to='/people'>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgPeople />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.people')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<Divider />
|
||||
<NavLink to='/settings'>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgSettings />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.settings')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<MenuItem onClick={() => showSendFeedback!()} style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgFeedback />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.sendFeedback')} />
|
||||
</MenuItem>
|
||||
</>
|
||||
)
|
||||
|
||||
const anchor = theme.direction === 'rtl' ? 'right' : 'left'
|
||||
return (
|
||||
<div id='home'>
|
||||
<HomeHeader sidebar={this.state.sidebarOpen} sidebarStatus={this.state.sidebarStatus} />
|
||||
<Sidebar overlay={this.sidebarOverlay} open={this.sidebar} status={this.sidebarStatus}>
|
||||
<SidebarContent>
|
||||
<MenuList style={{ color: 'rgb(117, 117, 117)', width: '210px' }}>
|
||||
{this.state.sidebarOverlay
|
||||
? <div>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgArrowLeft viewBox='0 3 24 24' style={{ color: '#fff', marginLeft: '15px', width: '32px', height: '32px', cursor: 'pointer' }} />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset
|
||||
primary={<span style={{ color: 'rgb(117, 117, 117)' }}
|
||||
className='sidebar__title'>{config.settings.appName}</span>} />
|
||||
</MenuItem>
|
||||
<Divider /></div>
|
||||
: ''
|
||||
}
|
||||
|
||||
<NavLink to='/'>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgHome />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.home')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<NavLink to={`/${this.props.uid}`}>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgAccountCircle />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.profile')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<NavLink to='/people'>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgPeople />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.people')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<Divider />
|
||||
<NavLink to='/settings'>
|
||||
<MenuItem style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgSettings />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.settings')} />
|
||||
</MenuItem>
|
||||
</NavLink>
|
||||
<MenuItem onClick={() => showSendFeedback!()} style={{ color: 'rgb(117, 117, 117)' }}>
|
||||
<ListItemIcon>
|
||||
<SvgFeedback />
|
||||
</ListItemIcon>
|
||||
<ListItemText inset primary={translate!('sidebar.sendFeedback')} />
|
||||
</MenuItem>
|
||||
</MenuList>
|
||||
</SidebarContent>
|
||||
|
||||
<SidebarMain>
|
||||
<div className={classes.root}>
|
||||
<div className={classes.appFrame}>
|
||||
<HomeHeader onToggleDrawer={this.handleDrawerToggle} drawerStatus={this.state.drawerOpen} />
|
||||
<Hidden mdUp>
|
||||
<Drawer
|
||||
variant='temporary'
|
||||
anchor={anchor}
|
||||
open={this.state.drawerOpen}
|
||||
classes={{
|
||||
paper: classes.drawerPaper,
|
||||
}}
|
||||
onClose={this.handleDrawerToggle}
|
||||
ModalProps={{
|
||||
keepMounted: true, // Better open performance on mobile.
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div className={classes.drawerHeader} />
|
||||
<MenuList style={{ color: 'rgb(117, 117, 117)', width: '210px' }}>
|
||||
<Divider />
|
||||
{drawer}
|
||||
</MenuList>
|
||||
</div>
|
||||
</Drawer>
|
||||
</Hidden>
|
||||
<Hidden smDown implementation='js'>
|
||||
<Drawer
|
||||
variant='persistent'
|
||||
open={this.state.drawerOpen}
|
||||
classes={{
|
||||
paper: classes.drawerPaperLarge,
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<MenuList className={classes.menu} style={{ color: 'rgb(117, 117, 117)', width: '210px' }}>
|
||||
{drawer}
|
||||
</MenuList>
|
||||
</div>
|
||||
</Drawer>
|
||||
</Hidden>
|
||||
<main
|
||||
className={classNames(classes.content, classes[`content-${anchor}`], {
|
||||
[classes.contentShift]: drawerOpen,
|
||||
[classes[`contentShift-${anchor}`]]: drawerOpen,
|
||||
})}
|
||||
>
|
||||
<HR enabled={loaded!} data={{ mergedPosts, loadDataStream, hasMorePosts }} />
|
||||
</SidebarMain>
|
||||
</Sidebar>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
@@ -280,4 +366,4 @@ const mapStateToProps = (state: any, ownProps: IHomeComponentProps) => {
|
||||
}
|
||||
|
||||
// - Connect component to redux store
|
||||
export default withRouter<any>(connect(mapStateToProps, mapDispatchToProps)(HomeComponent as any)) as typeof HomeComponent
|
||||
export default withRouter<any>(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any, { withTheme: true })(HomeComponent as any) as any)) as typeof HomeComponent
|
||||
|
||||
@@ -113,4 +113,14 @@ export interface IHomeComponentProps {
|
||||
*/
|
||||
translate?: (state: any) => any
|
||||
|
||||
/**
|
||||
* Styles
|
||||
*/
|
||||
classes?: any
|
||||
|
||||
/**
|
||||
* Theme
|
||||
*/
|
||||
theme?: any
|
||||
|
||||
}
|
||||
|
||||
@@ -2,26 +2,7 @@
|
||||
export interface IHomeComponentState {
|
||||
|
||||
/**
|
||||
* Change sidebar status to {open(status:true)/close(status:false)}
|
||||
*
|
||||
* @type {(status: boolean, state: string)}
|
||||
* @memberof IHomeComponentState
|
||||
* Whether drawer is open
|
||||
*/
|
||||
sidebarOpen: (status: boolean, source: string) => void
|
||||
|
||||
/**
|
||||
* Sidebar status
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof IHomeComponentState
|
||||
*/
|
||||
sidebarStatus: boolean
|
||||
|
||||
/**
|
||||
* Sidebar overlay status
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof IHomeComponentState
|
||||
*/
|
||||
sidebarOverlay: boolean
|
||||
drawerOpen: boolean
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import React, { Component } from 'react'
|
||||
import { NavLink } from 'react-router-dom'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
// - Material UI
|
||||
import SvgDehaze from 'material-ui-icons/Dehaze'
|
||||
import { grey, blue } from 'material-ui/colors'
|
||||
import Toolbar from 'material-ui/Toolbar'
|
||||
@@ -10,8 +12,8 @@ import Popover from 'material-ui/Popover'
|
||||
import AppBar from 'material-ui/AppBar'
|
||||
import Menu, { MenuList, MenuItem } from 'material-ui/Menu'
|
||||
import Paper from 'material-ui/Paper'
|
||||
import Hidden from 'material-ui/Hidden'
|
||||
import NotificationsIcon from 'material-ui-icons/Notifications'
|
||||
import EventListener, { withOptions } from 'react-event-listener'
|
||||
import Tooltip from 'material-ui/Tooltip'
|
||||
import Typography from 'material-ui/Typography'
|
||||
import { Manager, Target, Popper } from 'react-popper'
|
||||
@@ -92,13 +94,8 @@ export class HomeHeaderComponent extends Component<IHomeHeaderComponentProps, IH
|
||||
|
||||
// On click toggle sidebar
|
||||
onToggleSidebar = () => {
|
||||
if (this.props.sidebarStatus) {
|
||||
this.props.sidebar!(false, 'onToggle')
|
||||
|
||||
} else {
|
||||
this.props.sidebar!(true, 'onToggle')
|
||||
|
||||
}
|
||||
const {onToggleDrawer} = this.props
|
||||
onToggleDrawer()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,29 +150,19 @@ export class HomeHeaderComponent extends Component<IHomeHeaderComponentProps, IH
|
||||
})
|
||||
}
|
||||
|
||||
handleKeyUp = () => {
|
||||
// TODO: Handle key up on press ESC to close menu
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle resize event for window to manipulate home header status
|
||||
* @param {event} evt is the event is passed by winodw resize event
|
||||
*/
|
||||
handleResize = (event: any) => {
|
||||
|
||||
const {drawerStatus} = this.props
|
||||
// Set initial state
|
||||
let width = window.innerWidth
|
||||
|
||||
if (width >= 600 && !this.state.showTitle) {
|
||||
this.setState({
|
||||
showTitle: true
|
||||
})
|
||||
if (width >= 600 && !drawerStatus) {
|
||||
this.onToggleSidebar()
|
||||
} else if (width < 600) {
|
||||
|
||||
} else if (width < 600 && this.state.showTitle) {
|
||||
|
||||
this.setState({
|
||||
showTitle: false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,11 +177,6 @@ export class HomeHeaderComponent extends Component<IHomeHeaderComponentProps, IH
|
||||
|
||||
<AppBar position='fixed' color='secondary'>
|
||||
<Toolbar>
|
||||
<EventListener
|
||||
target='window'
|
||||
onResize={this.handleResize}
|
||||
onKeyUp={this.handleKeyUp}
|
||||
/>
|
||||
{/* Left side */}
|
||||
|
||||
<IconButton onClick={this.onToggleSidebar} >
|
||||
@@ -205,7 +187,9 @@ export class HomeHeaderComponent extends Component<IHomeHeaderComponentProps, IH
|
||||
{config.settings.appName}
|
||||
</Typography>
|
||||
<div className='homeHeader__title-root'>
|
||||
{this.state.showTitle ? <div className='homeHeader__title'>{this.props.title}</div> : ''}
|
||||
<Hidden smDown>
|
||||
<div className='homeHeader__title'>{this.props.title}</div>
|
||||
</Hidden>
|
||||
</div>
|
||||
|
||||
{/* Notification */}
|
||||
|
||||
@@ -7,7 +7,7 @@ export interface IHomeHeaderComponentProps {
|
||||
* @type {boolean}
|
||||
* @memberof IHomeHeaderComponentProps
|
||||
*/
|
||||
sidebarStatus?: boolean
|
||||
drawerStatus: boolean
|
||||
|
||||
/**
|
||||
* Logout user
|
||||
@@ -59,7 +59,7 @@ export interface IHomeHeaderComponentProps {
|
||||
*
|
||||
* @memberof IHomeHeaderComponentProps
|
||||
*/
|
||||
sidebar?: (status: boolean, source: string) => void
|
||||
onToggleDrawer: () => void
|
||||
|
||||
/**
|
||||
* Material ui theme style
|
||||
|
||||
@@ -112,8 +112,7 @@ export class PeopleComponent extends Component<IPeopleComponentProps,IPeopleComp
|
||||
*/
|
||||
const styles = {
|
||||
people: {
|
||||
margin: '0 auto',
|
||||
width: '90%'
|
||||
margin: '0 auto'
|
||||
},
|
||||
headline: {
|
||||
fontSize: 24,
|
||||
|
||||
@@ -62,8 +62,6 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
|
||||
*/
|
||||
const styles = {
|
||||
profile: {
|
||||
margin: '0 auto',
|
||||
width: '90%'
|
||||
},
|
||||
header: {
|
||||
|
||||
|
||||
@@ -27,12 +27,12 @@ export class HomeRouter extends Component<IRouterProps, any> {
|
||||
<PrivateRoute path='/people/:tab?' component={<People />} />
|
||||
|
||||
<PrivateRoute path='/tag/:tag' component={(
|
||||
<div className='blog'><St displayWriting={false} homeTitle={`#${match.params.tag}`} posts={data.mergedPosts} /></div>
|
||||
<div><St displayWriting={false} homeTitle={`#${match.params.tag}`} posts={data.mergedPosts} /></div>
|
||||
)} />
|
||||
<Route path='/:userId/posts/:postId/:tag?' component={PostPage} />
|
||||
<Route path='/:userId' component={Profile} />
|
||||
<PrivateRoute path='/' component={(
|
||||
<div className='blog'>
|
||||
<div>
|
||||
<St
|
||||
homeTitle={translate!('header.home')}
|
||||
posts={data.mergedPosts}
|
||||
|
||||
@@ -837,10 +837,6 @@ g__input-underline::after {
|
||||
overflow: hidden;
|
||||
margin-left: 15px; }
|
||||
|
||||
.blog {
|
||||
margin: 0 auto;
|
||||
width: 90%; }
|
||||
|
||||
@media (min-width: 993px) {
|
||||
.blog__right-list {
|
||||
margin-left: 2%; } }
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
.blog{
|
||||
margin: 0 auto;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.blog__right-list{
|
||||
|
||||
@media (min-width: 993px) {
|
||||
|
||||
Reference in New Issue
Block a user