GatsbyJSにドロワーメニューを追加する
01 27, 2019
ドロワーメニューを追加したい。
カテゴリーをドロワーメニューで表示したい欲が出てきたので実装する。
しかし、ドロワーを1から書くにはJSの理解レベルが足りない。
そこで今回はMaterialUIに泣きついた。
やったこと
- Material-UIのインストール
- Headerを実装
- categorylistを作成
Material-UIのインストール
npm install --save @material-ui/core
npm install --save @material-ui/icons
Headerを実装
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import { Link } from 'gatsby';
const styles = {
list: {
width: 250,
},
root: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
class Header extends Component {
state = {
left: false,
};
toggleDrawer = (side, open) => () => {
this.setState({
[side]: open,
});
};
render () {
const { classes } = this.props;
const sideList = (
<div className={classes.list}>
<List>
<Link to="/">
<ListItem button>
<ListItemText primary="Home" />
</ListItem>
</Link>
<Link to="/about">
<ListItem button>
<ListItemText primary="About" />
</ListItem>
</Link>
</List>
</div>
);
return (
<div className={classes.root}>
<AppBar position="relative" color="inherit">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleDrawer('left', true)}>
<MenuIcon />
</IconButton>
<Drawer open={this.state.left} onClose={this.toggleDrawer('left', false)}>
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('left', false)}
onKeyDown={this.toggleDrawer('left', false)}
>
{sideList}
</div>
</Drawer>
<strong>
<Link to="/" style={{ boxShadow: 'none', textDecoration: 'none', color: 'inherit', fontFamily: 'Montserrat, sans-serif', }}>Post Bank Extra</Link>
</strong>
</Toolbar>
</AppBar>
</div>
);
}
}
Header.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Header);
これにあとは自分のカテゴリーリストを載せる。
カテゴリーリストの実装
import React from 'react'
import { StaticQuery, graphql } from 'gatsby'
import ListItem from '@material-ui/core/ListItem';
import Button from '@material-ui/core/Button';
import ListItemText from '@material-ui/core/ListItemText';
const CategoryLists = () => (
<StaticQuery
query={graphql`
query{
allMarkdownRemark(filter: {frontmatter: {pagetype: {eq: "category"}}}) {
edges{
node{
frontmatter{
categoryslug
categoryname
}
}
}
}
}
`}
render={(data) => {
const posts = data.allMarkdownRemark.edges
return (
<div>
{posts.map(({ node }) => {
return (
<ListItem button key={node.frontmatter.categoryslug}>
<ListItemText primary={node.frontmatter.categoryname}></ListItemText>
</ListItem>
)
})}
</div>
);
}}
/>
)
export default CategoryLists
そして組み込む
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import { Link } from 'gatsby';
import CategoryLists from '../categorylists';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faHome,faUtensils,faQuestion} from '@fortawesome/free-solid-svg-icons'
const styles = {
list: {
width: 250,
},
root: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
class Header extends Component {
state = {
left: false,
};
toggleDrawer = (side, open) => () => {
this.setState({
[side]: open,
});
};
render () {
const { classes } = this.props;
const sideList = (
<div className={classes.list}>
<List>
<Link to="/">
<ListItem button>
<FontAwesomeIcon icon={faHome} />
<ListItemText primary="Home" />
</ListItem>
</Link>
<CategoryLists />
<Link to="/about">
<ListItem button>
<FontAwesomeIcon icon={faQuestion} />
<ListItemText primary="About" />
</ListItem>
</Link>
</List>
</div>
);
return (
<div className={classes.root}>
<AppBar position="relative" color="inherit">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu" onClick={this.toggleDrawer('left', true)}>
<MenuIcon />
</IconButton>
<Drawer open={this.state.left} onClose={this.toggleDrawer('left', false)}>
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('left', false)}
onKeyDown={this.toggleDrawer('left', false)}
>
{sideList}
</div>
</Drawer>
<strong>
<Link to="/" style={{ boxShadow: 'none', textDecoration: 'none', color: 'inherit', fontFamily: 'Montserrat, sans-serif', }}>corydoras</Link>
</strong>
</Toolbar>
</AppBar>
</div>
);
}
}
Header.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(Header);
StaticQueryで実装。便利。
実働
出来なかったこと
frontmatterにicon設定してリストレンダリングしようとしましたができませんでした。