Skip to content

Commit fd8164d

Browse files
Clickinclaude
andcommitted
docs(blog): micronaut-1 한국 맥락 보강 및 섹션 재편
- 한국 Spring 전파 섹션을 독립 ## 2) 섹션으로 분리 - eGovFrame(2009) 등장 배경, 제도적 강제력, 민간 파급 내용 추가 (출처: NIA 보도자료, 행정규칙, 정책브리핑, KLDP·ZDNet 당시 자료) - blog-post-reviewer 지적 사항 수정: - Google Guice 오픈소스 공개 연도 2006 → 2007년 3월로 수정 - [^reflection_bottlneck] 오타 수정 → reflection_bottleneck - [^7] 각주 이름 → spring_native_aot 로 변경 - AWS Lambda 2014년 "발표/preview" 맥락 각주 추가 - "혁명적이었습니다" 과장 표현 → "대폭 단순했습니다" - Series.astro: <details> 기반 접기/펼치기 + sessionStorage 상태 유지 - blog/index.astro: 동일 날짜 연작의 order 내림차순 정렬, 시리즈 배지 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7b8416e commit fd8164d

3 files changed

Lines changed: 190 additions & 55 deletions

File tree

src/components/Series.astro

Lines changed: 83 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,86 @@ const seriesPosts = posts
1919
});
2020
---
2121

22-
{
23-
seriesPosts.length > 0 && (
24-
<nav class="series-container mb-8 p-4 bg-[var(--color-bg-secondary)] rounded-lg border border-[var(--color-border)]" aria-label={`Series: ${series}`}>
25-
<h3 class="text-sm font-bold uppercase tracking-wider text-[var(--color-text-secondary)] mb-3">
26-
Series: {series}
27-
</h3>
28-
<ul class="space-y-2">
29-
{seriesPosts.map((post) => {
30-
const isCurrent = post.slug === currentSlug;
31-
return (
32-
<li class="flex items-start gap-2">
33-
<span class="mt-1.5 w-1.5 h-1.5 rounded-full bg-[var(--color-text-secondary)] flex-shrink-0 opacity-50" />
34-
{isCurrent ? (
35-
<span class="text-sm font-medium text-[var(--color-accent)]">
36-
{post.data.title}
37-
<span class="ml-2 text-xs text-[var(--color-text-secondary)] font-normal">(Current)</span>
38-
</span>
39-
) : (
40-
<a
41-
href={`/blog/${post.slug}`}
42-
class="text-sm text-[var(--color-text)] hover:text-[var(--color-accent)] transition-colors"
43-
>
44-
{post.data.title}
45-
</a>
46-
)}
47-
</li>
48-
);
49-
})}
50-
</ul>
51-
</nav>
52-
)
53-
}
22+
{seriesPosts.length > 0 && (
23+
<details
24+
id="series-nav"
25+
data-series={series}
26+
open
27+
class="mb-8 rounded-lg border border-[var(--color-border)] bg-[var(--color-bg-secondary)] overflow-hidden"
28+
>
29+
<summary class="series-summary flex items-center justify-between gap-4 px-4 py-3 cursor-pointer select-none hover:bg-[var(--color-border)]/20 transition-colors">
30+
<span class="text-sm font-bold uppercase tracking-wider text-[var(--color-text-secondary)]">
31+
시리즈: {series}
32+
<span class="ml-1.5 font-normal normal-case tracking-normal">({seriesPosts.length}편)</span>
33+
</span>
34+
<svg
35+
class="series-chevron w-4 h-4 text-[var(--color-text-secondary)] transition-transform duration-200 flex-shrink-0"
36+
viewBox="0 0 24 24"
37+
fill="none"
38+
stroke="currentColor"
39+
stroke-width="2"
40+
stroke-linecap="round"
41+
stroke-linejoin="round"
42+
aria-hidden="true"
43+
>
44+
<polyline points="6 9 12 15 18 9" />
45+
</svg>
46+
</summary>
47+
<ol class="space-y-2 px-4 pb-4 pt-1" type="1">
48+
{seriesPosts.map((post) => {
49+
const isCurrent = post.slug === currentSlug;
50+
return (
51+
<li class="flex items-start gap-2">
52+
<span class="mt-1.5 w-1.5 h-1.5 rounded-full bg-[var(--color-text-secondary)] flex-shrink-0 opacity-50" />
53+
{isCurrent ? (
54+
<span class="text-sm font-medium text-[var(--color-accent)]">
55+
{post.data.title}
56+
<span class="ml-2 text-xs text-[var(--color-text-secondary)] font-normal">(현재)</span>
57+
</span>
58+
) : (
59+
<a
60+
href={`/blog/${post.slug}`}
61+
class="text-sm text-[var(--color-text)] hover:text-[var(--color-accent)] transition-colors"
62+
>
63+
{post.data.title}
64+
</a>
65+
)}
66+
</li>
67+
);
68+
})}
69+
</ol>
70+
</details>
71+
)}
72+
73+
<style>
74+
.series-summary {
75+
list-style: none;
76+
}
77+
.series-summary::-webkit-details-marker {
78+
display: none;
79+
}
80+
</style>
81+
82+
<script>
83+
const el = document.getElementById("series-nav") as HTMLDetailsElement | null;
84+
if (el) {
85+
const key = `series-open:${el.dataset.series ?? ""}`;
86+
const chevron = el.querySelector(".series-chevron") as SVGElement | null;
87+
88+
function syncChevron(open: boolean) {
89+
if (chevron) chevron.style.transform = open ? "rotate(180deg)" : "";
90+
}
91+
92+
// sessionStorage는 탭 세션 내 뒤로가기/앞으로가기 전체에서 유지됨
93+
const saved = sessionStorage.getItem(key);
94+
if (saved !== null) {
95+
el.open = saved === "true";
96+
}
97+
syncChevron(el.open);
98+
99+
el.addEventListener("toggle", () => {
100+
sessionStorage.setItem(key, String(el.open));
101+
syncChevron(el.open);
102+
});
103+
}
104+
</script>

0 commit comments

Comments
 (0)