Use material design for side panel drawer

Change-Id: I7c89f3022accd6cda524fded63fe84e42e2fab62
This commit is contained in:
Manuel Stahl 2019-03-12 14:29:48 +01:00
parent 0dc4375f60
commit 032b2e0015
8 changed files with 172 additions and 118 deletions

View File

@ -1,20 +1,142 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom'
import PropTypes from 'prop-types';
import { SidePanel } from './';
import AppBar from '@material-ui/core/AppBar';
import CssBaseline from '@material-ui/core/CssBaseline';
import Divider from '@material-ui/core/Divider';
import Drawer from '@material-ui/core/Drawer';
import Hidden from '@material-ui/core/Hidden';
import IconButton from '@material-ui/core/IconButton';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import MenuIcon from '@material-ui/icons/Menu';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import { withStyles } from '@material-ui/core/styles';
import matrixLogo from '../../images/matrix-logo.svg';
export default class Layout extends Component {
const drawerWidth = 180;
const styles = theme => ({
root: {
display: 'flex',
},
drawer: {
[theme.breakpoints.up('sm')]: {
width: drawerWidth,
flexShrink: 0,
},
},
appBar: {
marginLeft: drawerWidth,
[theme.breakpoints.up('sm')]: {
width: `calc(100% - ${drawerWidth}px)`,
},
},
menuButton: {
marginRight: 20,
[theme.breakpoints.up('sm')]: {
display: 'none',
},
},
toolbar: theme.mixins.toolbar,
drawerPaper: {
width: drawerWidth,
},
content: {
flexGrow: 1,
padding: theme.spacing.unit * 3,
},
});
class Layout extends Component {
static propTypes = {
children: PropTypes.node,
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
};
state = {
mobileOpen: false,
};
handleDrawerToggle = () => {
this.setState(state => ({ mobileOpen: !state.mobileOpen }));
};
render() {
return (
<div className="common-layout">
<SidePanel />
<div className="common-page-container">
{this.props.children}
const { classes, theme } = this.props;
const { pathname } = this.props.location;
const drawer = (
<div>
<div className={classes.toolbar}>
<img src={matrixLogo} className="drawer-logo" alt="logo" />
</div>
<Divider />
<List>
<ListItem button key="Users" selected={pathname === "/user-admin"}
component={Link} to="/user-admin">
<ListItemText primary="Users" />
</ListItem>
</List>
</div>
);
return (
<div className={classes.root}>
<CssBaseline />
<AppBar position="fixed" className={classes.appBar}>
<Toolbar>
<IconButton
color="inherit"
aria-label="Open drawer"
onClick={this.handleDrawerToggle}
className={classes.menuButton}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" noWrap>
Synapse admin
</Typography>
</Toolbar>
</AppBar>
<nav className={classes.drawer}>
{/* The implementation can be swapped with js to avoid SEO duplication of links. */}
<Hidden smUp implementation="css">
<Drawer
container={this.props.container}
variant="temporary"
anchor={theme.direction === 'rtl' ? 'right' : 'left'}
open={this.state.mobileOpen}
onClose={this.handleDrawerToggle}
classes={{
paper: classes.drawerPaper,
}}
>
{drawer}
</Drawer>
</Hidden>
<Hidden xsDown implementation="css">
<Drawer
variant="permanent"
open
classes={{
paper: classes.drawerPaper,
}}
>
{drawer}
</Drawer>
</Hidden>
</nav>
<main className={classes.content}>
<div className={classes.toolbar} />
{this.props.children}
</main>
</div>
);
}
}
export default withStyles(styles, { withTheme: true })(Layout);

View File

@ -1,5 +1,6 @@
@import '../../styles/mixins';
.common-layout {
padding-left: 260px;
.drawer-logo {
margin: 10%;
width: 80%;
}

View File

@ -1,51 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import matrixLogo from '../../images/matrix-logo.svg';
import * as actions from './redux/actions';
export class SidePanel extends Component {
static propTypes = {
common: PropTypes.object.isRequired,
actions: PropTypes.object.isRequired,
};
render() {
return (
<div className="common-side-panel">
<div className="header">
<img src={matrixLogo} className="app-logo" alt="logo" />
</div>
<ul className="nav">
<li>
<NavLink to="/user-admin">Users</NavLink>
</li>
<li>
<NavLink to="/room-admin">Rooms</NavLink>
</li>
</ul>
</div>
);
}
}
/* istanbul ignore next */
function mapStateToProps(state) {
return {
common: state.common,
};
}
/* istanbul ignore next */
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({ ...actions }, dispatch),
};
}
export default connect(
mapStateToProps,
mapDispatchToProps,
)(SidePanel);

View File

@ -1,37 +0,0 @@
@import '../../styles/mixins';
.common-side-panel {
position: fixed;
box-sizing: border-box;
overflow: auto;
top: 0;
left: 0;
margin: 0;
width: 260px;
height: 100%;
background-color: #EEE;
.app-logo {
margin: 30px;
width: 200px;
}
ul,
li {
padding: 0;
margin: 0;
list-style: none;
}
a {
display: block;
padding: 8px;
padding-left: 24px;
text-decoration: none;
color: black;
}
a.active {
font-weight: bold;
background-color: #CCC;
}
}

View File

@ -1,3 +1,2 @@
export { default as PageNotFound } from './PageNotFound';
export { default as SidePanel } from './SidePanel';
export { default as Layout } from './Layout';

View File

@ -1,3 +1,2 @@
@import '../../styles/mixins';
@import './SidePanel';
@import './Layout';

View File

@ -0,0 +1,40 @@
// Small tablets and large smartphones (landscape view)
$screen-sm-min: 576px;
// Small tablets (portrait view)
$screen-md-min: 768px;
// Tablets and small desktops
$screen-lg-min: 992px;
// Large tablets and desktops
$screen-xl-min: 1200px;
// Small devices
@mixin sm {
@media (min-width: #{$screen-sm-min}) {
@content;
}
}
// Medium devices
@mixin md {
@media (min-width: #{$screen-md-min}) {
@content;
}
}
// Large devices
@mixin lg {
@media (min-width: #{$screen-lg-min}) {
@content;
}
}
// Extra large devices
@mixin xl {
@media (min-width: #{$screen-xl-min}) {
@content;
}
}

View File

@ -1,19 +0,0 @@
import React from 'react';
import { shallow } from 'enzyme';
import { SidePanel } from '../../../src/features/common/SidePanel';
describe('common/SidePanel', () => {
it('renders node with correct class name', () => {
const props = {
common: {},
actions: {},
};
const renderedComponent = shallow(
<SidePanel {...props} />
);
expect(
renderedComponent.find('.common-side-panel').length
).toBe(1);
});
});