Skip to content
This repository was archived by the owner on May 29, 2024. It is now read-only.

Commit 6d78e73

Browse files
authored
[Feature] Beautify home page using material UI (#141)
* chore: implement template of home page * chore: show dungeon info on card * chore: add material ui icons * chore: add dungeon info * fix(typos): dugeon to dungeon * chore: do not show dungeon if does not have info * chore: hide appbar on init * chore: add image for each dungeon
1 parent abb467b commit 6d78e73

File tree

12 files changed

+456
-17
lines changed

12 files changed

+456
-17
lines changed

gatsby-config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ require('dotenv').config({
55
module.exports = {
66
siteMetadata: {
77
title: `Markdown Dungeon`,
8+
siteUrl: `https://markdown-dungeon.netlify.app/`,
89
description: `A dungeon is a room or cell in which prisoners are held, especially underground`,
910
},
1011
plugins: [

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,17 @@
1010
"serve": "gatsby serve"
1111
},
1212
"dependencies": {
13+
"@material-ui/core": "^4.11.3",
14+
"@material-ui/icons": "^4.11.2",
1315
"gatsby": "^2.24.67",
1416
"gatsby-image": "^2.4.20",
1517
"gatsby-plugin-catch-links": "^2.3.14",
1618
"gatsby-plugin-manifest": "^2.4.33",
1719
"gatsby-plugin-offline": "^3.2.30",
1820
"gatsby-plugin-react-helmet": "^3.3.12",
1921
"gatsby-plugin-sharp": "^2.6.38",
20-
"gatsby-remark-autolink-headers": "^2.3.14",
2122
"gatsby-plugin-typography": "^2.5.12",
23+
"gatsby-remark-autolink-headers": "^2.3.14",
2224
"gatsby-remark-prismjs": "^3.5.15",
2325
"gatsby-source-filesystem": "^2.3.32",
2426
"gatsby-transformer-remark": "^2.8.37",
@@ -27,11 +29,11 @@
2729
"prismjs": "^1.21.0",
2830
"prop-types": "^15.7.2",
2931
"react": "^16.8.6",
32+
"react-device-detect": "^1.14.0",
3033
"react-dom": "^16.8.6",
3134
"react-helmet": "^6.1.0",
3235
"react-scripts": "^3.4.3",
3336
"react-typography": "^0.16.19",
34-
"react-device-detect": "^1.14.0",
3537
"typography": "^0.16.19",
3638
"typography-plugin-code": "^0.16.19",
3739
"typography-theme-github": "^0.16.19"

src/components/card-grid.jsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import React from 'react';
2+
import Button from '@material-ui/core/Button';
3+
import Card from '@material-ui/core/Card';
4+
import CardActions from '@material-ui/core/CardActions';
5+
import CardContent from '@material-ui/core/CardContent';
6+
import CardMedia from '@material-ui/core/CardMedia';
7+
import Typography from '@material-ui/core/Typography';
8+
import infos from '../data/dungeon-info.json';
9+
import Grid from '@material-ui/core/Grid';
10+
import { homeStyles } from '../utils/styles';
11+
import ArrowForwardIcon from '@material-ui/icons/ArrowForward';
12+
13+
export default function CardGrid(props) {
14+
const classes = homeStyles();
15+
const post = props.post;
16+
const slug = post.fields.slug;
17+
const splited = slug.split('/');
18+
const info = infos.find(
19+
(d) => d.name === splited[2] && d.language === splited[1]
20+
);
21+
post.excerpt = post.excerpt.replace(' 🤠開始', '');
22+
return (
23+
info ?
24+
<Grid item xs={12} sm={6} md={4}>
25+
<Card className={classes.card}>
26+
<CardMedia
27+
className={classes.cardMedia}
28+
image={info.image === '' ? '../../images/dungeon.jpg' : `../../images/${info.image}`}
29+
title='Image title'
30+
/>
31+
<CardContent className={classes.cardContent}>
32+
<Typography gutterBottom variant='h5' component='h2'>
33+
{info.display}
34+
</Typography>
35+
<Typography>{post.excerpt}</Typography>
36+
</CardContent>
37+
<CardActions dir='rtl'>
38+
<Button size='small' color='primary' href={slug.slice(0, -1)}>
39+
<ArrowForwardIcon />
40+
</Button>
41+
</CardActions>
42+
</Card>
43+
</Grid> : null
44+
);
45+
}

src/components/copyright.jsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import Typography from '@material-ui/core/Typography';
3+
import Link from '@material-ui/core/Link';
4+
5+
export default function Copyright() {
6+
return (
7+
<Typography variant='body2' color='textSecondary' align='center'>
8+
{'Copyright © '}
9+
<Link color='inherit' href='https://material-ui.com/'>
10+
Make Contributions
11+
</Link>{' '}
12+
{new Date().getFullYear()}
13+
{'.'}
14+
</Typography>
15+
);
16+
}

src/components/hide-appbar.jsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import AppBar from '@material-ui/core/AppBar';
4+
import Toolbar from '@material-ui/core/Toolbar';
5+
import Typography from '@material-ui/core/Typography';
6+
import CssBaseline from '@material-ui/core/CssBaseline';
7+
import useScrollTrigger from '@material-ui/core/useScrollTrigger';
8+
import Slide from '@material-ui/core/Slide';
9+
10+
function HideOnScroll(props) {
11+
const { children, window } = props;
12+
// Note that you normally won't need to set the window ref as useScrollTrigger
13+
// will default to window.
14+
// This is only being set here because the demo is in an iframe.
15+
const trigger = useScrollTrigger({ target: window ? window() : undefined });
16+
return (
17+
<Slide appear={false} direction="down" in={trigger}>
18+
{children}
19+
</Slide>
20+
);
21+
}
22+
23+
HideOnScroll.propTypes = {
24+
children: PropTypes.element.isRequired,
25+
/**
26+
* Injected by the documentation to work in an iframe.
27+
* You won't need it on your project.
28+
*/
29+
window: PropTypes.func,
30+
};
31+
32+
export default function HideAppBar(props) {
33+
return (
34+
<React.Fragment>
35+
<CssBaseline />
36+
<HideOnScroll {...props}>
37+
<AppBar>
38+
<Toolbar>
39+
<Typography variant='h6' color='inherit' noWrap>
40+
Markdown Dungeon
41+
</Typography>
42+
</Toolbar>
43+
</AppBar>
44+
</HideOnScroll>
45+
</React.Fragment>
46+
);
47+
}

src/data/dungeon-info.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[
2+
{
3+
"name": "normal-dungeon",
4+
"display": "The Normal Dungeon",
5+
"image": "",
6+
"language": "english"
7+
},
8+
{
9+
"name": "great-wall",
10+
"display": "長城",
11+
"image": "great-wall.jpg",
12+
"language": "chinese"
13+
},
14+
{
15+
"name": "covid-19",
16+
"display": "COVID-19",
17+
"image": "covid-19.jpg",
18+
"language": "english"
19+
},
20+
{
21+
"name": "normal-dungeon",
22+
"display": "O Calabouço Normal",
23+
"image": "",
24+
"language": "portuguese"
25+
}
26+
]

src/pages/index.jsx

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,75 @@
11
import React from 'react';
22
import { graphql } from 'gatsby';
3-
import Layout from '../components/layout';
3+
import CssBaseline from '@material-ui/core/CssBaseline';
4+
import Grid from '@material-ui/core/Grid';
5+
import Typography from '@material-ui/core/Typography';
6+
import Container from '@material-ui/core/Container';
7+
import Copyright from '../components/copyright';
8+
import CardGrid from '../components/card-grid';
9+
import HideAppBar from '../components/hide-appbar';
10+
import { homeStyles } from '../utils/styles';
411

512
export default function Home({ data }) {
6-
const post = data.markdownRemark;
7-
let html = post.html.replace(/.md/gi, '');
8-
html = html.replace(
9-
'./LICENSE',
10-
`${process.env.GATSBY_GITHUB_REPO_URL}/blob/master/LICENSE`
11-
);
13+
const classes = homeStyles();
14+
const posts = data.allMarkdownRemark.nodes;
15+
1216
return (
13-
<Layout>
14-
<div dangerouslySetInnerHTML={{ __html: html }} />
15-
</Layout>
17+
<React.Fragment>
18+
<CssBaseline />
19+
<HideAppBar />
20+
<main>
21+
{/* Hero unit */}
22+
<div className={classes.heroContent}>
23+
<Container maxWidth='sm'>
24+
<Typography
25+
component='h1'
26+
variant='h2'
27+
align='center'
28+
color='textPrimary'
29+
gutterBottom
30+
>
31+
Markdown Dungeon
32+
</Typography>
33+
<Typography
34+
variant='h5'
35+
align='center'
36+
color='textSecondary'
37+
paragraph
38+
>
39+
A dungeon is a room or cell in which prisoners are held,
40+
especially underground.
41+
</Typography>
42+
</Container>
43+
</div>
44+
<Container className={classes.cardGrid} maxWidth='md'>
45+
{/* End hero unit */}
46+
<Grid container spacing={4}>
47+
{posts.map((post, index) => (
48+
<CardGrid item key={index} post={post} />
49+
))}
50+
</Grid>
51+
</Container>
52+
</main>
53+
{/* Footer */}
54+
<footer className={classes.footer}>
55+
<Copyright />
56+
</footer>
57+
{/* End footer */}
58+
</React.Fragment>
1659
);
1760
}
1861

1962
export const query = graphql`
2063
query {
21-
markdownRemark(fields: { slug: { regex: "/README/" } }) {
22-
html
64+
allMarkdownRemark(
65+
filter: { fileAbsolutePath: { regex: "/begin-journey/" } }
66+
) {
67+
nodes {
68+
fields {
69+
slug
70+
}
71+
excerpt(truncate: true, pruneLength: 100)
72+
}
2373
}
2474
}
2575
`;

src/utils/styles.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { makeStyles } from '@material-ui/core/styles';
2+
3+
export const homeStyles = makeStyles((theme) => ({
4+
icon: {
5+
marginRight: theme.spacing(2),
6+
},
7+
heroContent: {
8+
backgroundColor: theme.palette.background.paper,
9+
padding: theme.spacing(8, 0, 6),
10+
},
11+
heroButtons: {
12+
marginTop: theme.spacing(4),
13+
},
14+
cardGrid: {
15+
paddingTop: theme.spacing(8),
16+
paddingBottom: theme.spacing(8),
17+
},
18+
card: {
19+
height: '100%',
20+
display: 'flex',
21+
flexDirection: 'column',
22+
},
23+
cardMedia: {
24+
paddingTop: '56.25%', // 16:9
25+
},
26+
cardContent: {
27+
flexGrow: 1,
28+
},
29+
footer: {
30+
backgroundColor: theme.palette.background.paper,
31+
padding: theme.spacing(6),
32+
},
33+
}));

static/images/covid-19.jpg

172 KB
Loading

static/images/dungeon.jpg

14 KB
Loading

static/images/great-wall.jpg

284 KB
Loading

0 commit comments

Comments
 (0)