[Improvement] Using material-ui drawer

This commit is contained in:
Qolzam
2018-02-21 17:44:32 +07:00
parent c81cfa9c44
commit cacb940b15
10 changed files with 226 additions and 177 deletions

View File

@@ -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

View File

@@ -113,4 +113,14 @@ export interface IHomeComponentProps {
*/
translate?: (state: any) => any
/**
* Styles
*/
classes?: any
/**
* Theme
*/
theme?: any
}

View File

@@ -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
}

View File

@@ -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 */}

View File

@@ -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

View File

@@ -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,

View File

@@ -62,8 +62,6 @@ export class ProfileComponent extends Component<IProfileComponentProps,IProfileC
*/
const styles = {
profile: {
margin: '0 auto',
width: '90%'
},
header: {

View File

@@ -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}

View File

@@ -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%; } }

View File

@@ -1,8 +1,3 @@
.blog{
margin: 0 auto;
width: 90%;
}
.blog__right-list{
@media (min-width: 993px) {