Skip to content

Commit 27e1172

Browse files
committed
Create react rendering page
0 parents  commit 27e1172

File tree

27 files changed

+9060
-0
lines changed

27 files changed

+9060
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
.next

components/Button.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
export default function Button({children, onClick}) {
2+
return (
3+
<>
4+
<button onClick={onClick}>{children}</button>
5+
<style jsx>{`
6+
button {
7+
align-items: center;
8+
background: transparent;
9+
border: 1px solid #ccc;
10+
border-radius: 50px;
11+
cursor: pointer;
12+
display: flex;
13+
padding: 4px 8px;
14+
}
15+
button:hover {
16+
background: #f0f0f0;
17+
}
18+
`}</style>
19+
</>
20+
)
21+
}

components/Card.js

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import CardImage from 'components/CardImage'
2+
import CardFooter from 'components/CardFooter'
3+
import CardHeader from 'components/CardHeader'
4+
5+
const {useState} = React
6+
7+
export default function Card({
8+
content,
9+
url,
10+
urlToImage,
11+
publishedAt,
12+
description,
13+
source,
14+
title
15+
}) {
16+
const [showMore, setShowMore] = useState(false)
17+
const [hover, setHover] = useState(false)
18+
19+
const handleReadMore = e => {
20+
e.preventDefault()
21+
e.stopPropagation()
22+
setShowMore(!showMore)
23+
}
24+
25+
return (
26+
<>
27+
<a
28+
href={url}
29+
onMouseOver={() => setHover(true)}
30+
onMouseLeave={() => setHover(false)}
31+
>
32+
<article itemScope itemType="http://schema.org/Article">
33+
<CardImage urlToImage={urlToImage} />
34+
<div>
35+
<CardHeader
36+
title={title}
37+
description={description}
38+
handleReadMore={handleReadMore}
39+
show={hover && !showMore}
40+
/>
41+
</div>
42+
43+
<p className={showMore ? 'show' : ''}>{content}</p>
44+
45+
<div>
46+
<CardFooter
47+
show={hover}
48+
source={source.name}
49+
publishedAt={publishedAt}
50+
url={url}
51+
title={title}
52+
/>
53+
</div>
54+
</article>
55+
</a>
56+
<style jsx>{`
57+
@keyframes scale {
58+
from {
59+
transform: scale(0.9);
60+
}
61+
to {
62+
transform: scale(1);
63+
}
64+
}
65+
66+
a {
67+
display: block;
68+
text-decoration: none;
69+
transition: all 0.3s ease;
70+
}
71+
72+
a:hover {
73+
transform: scale(1.05);
74+
}
75+
76+
a:hover .onHover {
77+
opacity: 1;
78+
}
79+
80+
.onHover {
81+
opacity: 0;
82+
transition: all 0.3s ease;
83+
}
84+
85+
div {
86+
padding-left: 96px;
87+
}
88+
89+
p {
90+
color: #000;
91+
font-size: 14px;
92+
line-height: 1.5;
93+
margin: 0;
94+
max-height: 0;
95+
overflow: hidden;
96+
transition: height 0.3s ease;
97+
}
98+
99+
p.show {
100+
max-height: 5000px;
101+
padding-top: 16px;
102+
}
103+
104+
a:hover article {
105+
box-shadow: rgba(0, 0, 0, 0.1) 0px 8px 24px;
106+
transition: all 0.2s ease-in 0s;
107+
}
108+
109+
article {
110+
animation: scale 1s ease-in-out;
111+
background: rgb(255, 255, 255);
112+
box-shadow: rgba(0, 0, 0, 0.08) 0px 4px 8px;
113+
border-radius: 8px;
114+
display: flex;
115+
flex-direction: column;
116+
padding: 16px;
117+
position: relative;
118+
transition: all 0.2s ease-out 0s;
119+
}
120+
`}</style>
121+
</>
122+
)
123+
}

components/CardFooter.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import TimeAgo from 'components/TimeAgo'
2+
import Share from 'components/Share'
3+
4+
export default function CardFooter({show, source, publishedAt, url, title}) {
5+
return (
6+
<>
7+
<footer>
8+
<div>
9+
<span>{source}</span>
10+
<TimeAgo date={publishedAt} />
11+
</div>
12+
<div className={show ? 'show' : 'hide'}>
13+
<Share url={url} title={title} />
14+
</div>
15+
</footer>
16+
<style jsx>{`
17+
footer {
18+
align-items: center;
19+
display: flex;
20+
justify-content: space-between;
21+
padding-top: 16px;
22+
}
23+
24+
footer div:first-child {
25+
display: flex;
26+
}
27+
28+
.hide {
29+
opacity: 0;
30+
transition: all 0.3s ease;
31+
}
32+
33+
.show {
34+
opacity: 1;
35+
transition: all 0.3s ease;
36+
}
37+
38+
span {
39+
color: #09f;
40+
font-size: 14px;
41+
padding-right: 8px;
42+
}
43+
`}</style>
44+
</>
45+
)
46+
}

components/CardHeader.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import {MdExpandMore} from 'react-icons/md'
2+
3+
export default function CardHeader({title, description, handleReadMore, show}) {
4+
return (
5+
<>
6+
<header>
7+
<h3 itemProp="name">{title}</h3>
8+
<h4 itemProp="description">
9+
{description}
10+
<button className={show ? 'show' : ''} onClick={handleReadMore}>
11+
Read more...<MdExpandMore size="16px" />
12+
</button>
13+
</h4>
14+
</header>
15+
<style jsx>{`
16+
h3 {
17+
font-size: 18px;
18+
font-weight: 100;
19+
color: #444;
20+
font-size: 20px;
21+
line-height: 1.25;
22+
margin: 0;
23+
padding-bottom: 8px;
24+
}
25+
26+
h4 {
27+
color: rgb(92, 97, 102);
28+
font-size: 14px;
29+
font-weight: 400;
30+
line-height: 1.5;
31+
margin: 0;
32+
}
33+
34+
button {
35+
background: transparent;
36+
border: 0;
37+
color: #09f;
38+
cursor: pointer;
39+
display: inline-flex;
40+
font-size: 12px;
41+
opacity: 0;
42+
transition: all 0.3s ease;
43+
}
44+
45+
button.show {
46+
opacity: 1;
47+
}
48+
`}</style>
49+
</>
50+
)
51+
}

components/CardImage.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const {useState, useEffect, useRef} = React
2+
3+
export default function CardImage({urlToImage}) {
4+
const [loaded, setLoaded] = useState(false)
5+
const imgRef = useRef()
6+
7+
useEffect(function() {
8+
const img = imgRef.current
9+
if (img && img.complete) {
10+
setLoaded(true)
11+
}
12+
}, [])
13+
14+
return (
15+
<>
16+
<figure>
17+
<div style={{backgroundImage: `url('${urlToImage}')`}} />
18+
<img
19+
className={loaded ? 'loaded' : ''}
20+
ref={imgRef}
21+
onLoad={() => setLoaded(true)}
22+
src={urlToImage}
23+
/>
24+
</figure>
25+
<style jsx>{`
26+
figure {
27+
height: 104px;
28+
left: -8px;
29+
margin: 0;
30+
position: absolute;
31+
top: -8px;
32+
width: 104px;
33+
z-index: 1;
34+
}
35+
36+
div {
37+
background-size: cover;
38+
filter: blur(12px);
39+
height: 100%;
40+
width: 100%;
41+
position: absolute;
42+
transform: scale(1.05);
43+
}
44+
45+
img {
46+
border-radius: 8px;
47+
height: 100%;
48+
object-fit: cover;
49+
opacity: 0;
50+
position: absolute;
51+
transition: opacity 1.5s ease;
52+
transition-delay: 1s;
53+
width: 100%;
54+
}
55+
56+
img.loaded {
57+
opacity: 1;
58+
}
59+
`}</style>
60+
</>
61+
)
62+
}

components/Footer.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
export default function Footer() {
2+
return (
3+
<>
4+
<footer>
5+
Developed by{' '}
6+
<svg width="20" height="20">
7+
<path d="M5 15a.502.502.0 0 1-.354-.146l-4-4a.5.5.0 0 1 0-.707l4-4a.5.5.0 0 1 .707.707L1.707 10.5l3.646 3.646a.5.5.0 0 1-.354.853zm10 0a.5.5.0 0 1-.354-.853l3.646-3.646-3.646-3.646a.5.5.0 0 1 .707-.707l4 4a.5.5.0 0 1 0 .707l-4 4a.498.498.0 0 1-.354.146zM7.5 15a.5.5.0 0 1-.424-.765l5-8a.5.5.0 0 1 .848.53l-5 8A.5.5.0 0 1 7.5 15z" />
8+
</svg>
9+
<a href="https://midu.dev">midudev</a>
10+
</footer>
11+
<style jsx>{`
12+
svg {
13+
background: #09f;
14+
border-radius: 16px;
15+
box-sizing: content-box;
16+
display: inline-block;
17+
fill: #fff;
18+
margin: 0 2px;
19+
padding: 4px;
20+
transform: scale(0.9);
21+
}
22+
footer {
23+
align-items: center;
24+
color: #555;
25+
display: flex;
26+
padding: 32px 0 16px;
27+
width: 100%;
28+
}
29+
a {
30+
border-bottom: 1px solid transparent;
31+
color: #09f;
32+
padding: 0px 2px;
33+
transition: all 0.3s ease;
34+
text-decoration: none;
35+
}
36+
a:hover {
37+
border-bottom: 1px solid #09f;
38+
}
39+
`}</style>
40+
</>
41+
)
42+
}

components/Grid.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export default function Grid({children}) {
2+
return (
3+
<>
4+
<section>{children}</section>
5+
<style jsx>{`
6+
section {
7+
display: grid;
8+
gap: 32px 32px;
9+
grid-template-columns: 1fr;
10+
margin-top: 32px;
11+
margin-left: 16px;
12+
max-width: 500px;
13+
}
14+
`}</style>
15+
</>
16+
)
17+
}

0 commit comments

Comments
 (0)