Skip to content

Commit 27162ae

Browse files
committed
feat: add article toggle button
1 parent c9f3dce commit 27162ae

File tree

6 files changed

+134
-19
lines changed

6 files changed

+134
-19
lines changed

src/components/ArticleCard.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ import { getFaviconUrl, type Article } from '../libs/articles';
55
66
interface Props {
77
article: Article;
8+
class?: string;
89
}
910
10-
const { article } = Astro.props;
11+
const { article, class: className } = Astro.props;
1112
1213
const date = dayjs(article.createdAt).format('YYYY-MM-DD');
1314
const faviconSrc = getFaviconUrl(article.site);
1415
---
1516

16-
<article>
17+
<article class={className}>
1718
<a href={article.url}>
1819
<h3>{article.title}</h3>
1920
<div class="info">

src/components/ArticleList.astro

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
import { getArticles } from '../libs/articles';
3+
import ArticleCard from './ArticleCard.astro';
4+
import ArticleListButton from './ArticleListButton.tsx';
5+
6+
const articles = await getArticles();
7+
---
8+
9+
<div class="container" id="article-list" style={{ '--display-all': 'none' }}>
10+
{
11+
articles.map((article, i) => (
12+
<ArticleCard
13+
article={article}
14+
class={i > 3 ? 'old-article' : undefined}
15+
/>
16+
))
17+
}
18+
<div class="spacer spacer-articles"></div>
19+
</div>
20+
21+
<div class="center">
22+
<ArticleListButton client:idle />
23+
</div>
24+
25+
<style>
26+
.container {
27+
display: flex;
28+
flex-wrap: wrap;
29+
gap: 16px;
30+
margin-top: 32px;
31+
}
32+
.spacer {
33+
height: 0;
34+
flex-grow: 1;
35+
flex-basis: 250px;
36+
}
37+
.center {
38+
display: flex;
39+
justify-content: center;
40+
}
41+
</style>
42+
43+
<style is:global>
44+
.old-article {
45+
display: var(--display-all);
46+
}
47+
</style>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.button {
2+
display: inline-block;
3+
padding: 4px 12px;
4+
border-radius: 8px;
5+
border: none;
6+
background: rgb(var(--text-color-rgb) / 0.08);
7+
display: flex;
8+
align-items: center;
9+
gap: 8px;
10+
}
11+
.button:hover {
12+
background: rgb(var(--text-color-rgb) / 0.12);
13+
}
14+
.icon {
15+
margin-top: -1px;
16+
}
17+
.label {
18+
font-weight: 600;
19+
}

src/components/ArticleListButton.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { useState } from 'preact/hooks';
2+
import Styles from './ArticleListButton.module.css';
3+
4+
const ArticleListButton = () => {
5+
const [open, setOpen] = useState(false);
6+
7+
return (
8+
<button
9+
className={Styles.button}
10+
onClick={() => {
11+
setOpen(!open);
12+
const listElm = document.getElementById('article-list');
13+
listElm?.style.setProperty('--display-all', !open ? 'block' : 'none');
14+
}}
15+
>
16+
{open ? (
17+
<>
18+
<svg
19+
viewBox="0 0 15 15"
20+
fill="none"
21+
xmlns="http://www.w3.org/2000/svg"
22+
width="15"
23+
height="15"
24+
className={Styles.icon}
25+
>
26+
<path
27+
d="M1 10l6.5-7 6.5 7"
28+
stroke="currentColor"
29+
stroke-linecap="square"
30+
></path>
31+
</svg>
32+
<span className={Styles.label}>直近の記事のみ表示</span>
33+
</>
34+
) : (
35+
<>
36+
<svg
37+
viewBox="0 0 15 15"
38+
fill="none"
39+
xmlns="http://www.w3.org/2000/svg"
40+
width="15"
41+
height="15"
42+
className={Styles.icon}
43+
>
44+
<path d="M7.5 1v13M1 7.5h13" stroke="currentColor"></path>
45+
</svg>
46+
<span className={Styles.label}>すべて表示</span>
47+
</>
48+
)}
49+
<slot />
50+
</button>
51+
);
52+
};
53+
54+
export default ArticleListButton;

src/pages/index.astro

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ import Hero from '../components/Hero.astro';
77
import Section from '../components/Section.astro';
88
import More from '../components/More.astro';
99
import WorkCard from '../components/WorkCard.astro';
10-
import { getArticles } from '../libs/articles';
11-
import ArticleCard from '../components/ArticleCard.astro';
10+
import ArticleList from '../components/ArticleList.astro';
1211
1312
const works = await getCollection('works', (w) => w.data.pinned);
14-
const articles = await getArticles();
1513
---
1614

1715
<Base title={null}>
@@ -27,22 +25,19 @@ const articles = await getArticles();
2725
</Section>
2826
<Section>
2927
<h2 id="works">Works</h2>
30-
<div class="container">
28+
<div class="works-container">
3129
{
3230
works
3331
.sort((a, b) => (a.data.date > b.data.date ? -1 : 1))
3432
.map((work) => <WorkCard work={work} />)
3533
}
36-
<div class="spacer spacer-works"></div>
34+
<div class="works-spacer"></div>
3735
</div>
3836
<More href="/works">つくったものをもっと見る</More>
3937
</Section>
4038
<Section>
4139
<h2>Articles</h2>
42-
<div class="container">
43-
{articles.map((article) => <ArticleCard article={article} />)}
44-
<div class="spacer spacer-articles"></div>
45-
</div>
40+
<ArticleList />
4641
</Section>
4742
<Footer />
4843
</main>
@@ -54,22 +49,17 @@ const articles = await getArticles();
5449
padding-top: 32px;
5550
border-radius: 32px 32px 0 0;
5651
}
57-
.container {
52+
.works-container {
5853
display: flex;
5954
flex-wrap: wrap;
6055
gap: 16px;
6156
margin-top: 32px;
6257
}
63-
.spacer {
58+
.works-spacer {
6459
height: 0;
6560
flex-grow: 1;
66-
}
67-
.spacer-works {
6861
flex-basis: 300px;
6962
}
70-
.spacer-articles {
71-
flex-basis: 250px;
72-
}
7363
</style>
7464

7565
<style is:global>

tsconfig.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
{
2-
"extends": "astro/tsconfigs/strict"
2+
"extends": "astro/tsconfigs/strict",
3+
"compilerOptions": {
4+
"jsx": "react-jsx",
5+
"jsxImportSource": "preact"
6+
}
37
}

0 commit comments

Comments
 (0)