Skip to content

Commit 2bdfc46

Browse files
author
lzm
committed
feat(blog): archive page overhaul — all 3 tiers
Replaces PaperMod's basic year/month grouping with 11 enhancements across 3 tiers, all in 8 new files. Tier 1 (visual, no JS): - Excerpt preview under each title (140-char truncated .Summary) - Category + tag chips on each entry - Series badge ('📚 <name>') linking to /series/<name>/ - Stats summary bar: 'N 篇 · M 标签 · K 系列 · ~X 字' - Color-coded left border per primary category (随笔=amber, 工具=cyan, 技术=violet — matches tags-rainbow) Tier 2 (pure-CSS interactivity, no JS): - Filter pills: 全部 + per-category pills - Compact / Detailed view toggle (hides excerpt + chips) - NEW badge (server-side: posts within 7 days) - All driven by hidden <input type=radio> + sibling selectors Tier 3 (client-side JS): - Search box: type to filter by title / excerpt / category - Sort dropdown: 最新/最早/标题 A-Z/Z-A/阅读时长 短→长 - Monthly histogram: bar chart of post counts per year-month - 'No results' placeholder - Vanilla JS, no deps; reads data-* attrs from server-rendered DOM File map: layouts/_default/archives.html — main override layouts/_partials/archive-stats.html — Tier 1 stats bar layouts/_partials/archive-filter.html — Tier 2 UI layouts/_partials/archive-search.html — Tier 3 UI assets/css/extended/archive-tier{1,2,3}.css — one CSS per tier static/js/archive-search.js — Tier 3 logic (NOTE: agent-based parallel dispatch was attempted first but the sub-sessions got stuck in startup; this commit is the coordinator's direct implementation of all 3 tiers.)
1 parent 10bc36f commit 2bdfc46

8 files changed

Lines changed: 826 additions & 0 deletions

File tree

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/* ===== Archive page — Tier 1 =====
2+
Visual: excerpts, chips, series badge, stats bar, color-coded borders
3+
*/
4+
5+
/* Stats summary bar */
6+
.archive-stats {
7+
display: flex;
8+
flex-wrap: wrap;
9+
gap: 0.5rem 0.8rem;
10+
align-items: center;
11+
margin: 1rem 0 1.5rem;
12+
padding: 0.6rem 1rem;
13+
border: 1px solid var(--border);
14+
border-radius: var(--radius, 8px);
15+
background: var(--entry);
16+
font-size: 0.9em;
17+
color: var(--secondary);
18+
}
19+
20+
.archive-stat {
21+
display: inline-flex;
22+
align-items: baseline;
23+
gap: 0.3rem;
24+
}
25+
26+
.archive-stat-num {
27+
font-weight: 600;
28+
color: var(--primary);
29+
font-variant-numeric: tabular-nums;
30+
}
31+
32+
.archive-stat-sep {
33+
color: var(--border);
34+
margin: 0 0.1rem;
35+
}
36+
37+
/* Archive year/month header tweaks (extend PaperMod's) */
38+
.archive-year {
39+
margin-top: 2rem;
40+
}
41+
42+
.archive-year:not(:last-of-type) {
43+
border-bottom: 2px solid var(--border);
44+
padding-bottom: 1rem;
45+
}
46+
47+
.archive-month {
48+
display: flex;
49+
align-items: flex-start;
50+
padding: 0.6rem 0;
51+
flex-wrap: wrap;
52+
}
53+
54+
.archive-month-header {
55+
margin: 0.5rem 0;
56+
width: 200px;
57+
font-size: 1.05em;
58+
}
59+
60+
.archive-month:not(:last-of-type) {
61+
border-bottom: 1px dashed var(--border);
62+
}
63+
64+
/* Archive entry — extends PaperMod's compact entry with our additions */
65+
.archive-entry {
66+
position: relative;
67+
padding: 0.6rem 0.8rem 0.6rem 1rem;
68+
margin: 0.6rem 0;
69+
border-left: 3px solid var(--border); /* fallback color; overridden below */
70+
border-radius: 0 var(--radius, 6px) var(--radius, 6px) 0;
71+
background: var(--entry);
72+
transition: transform 0.15s ease, border-color 0.15s ease;
73+
}
74+
75+
.archive-entry:hover {
76+
transform: translateX(2px);
77+
}
78+
79+
.archive-entry-head {
80+
display: flex;
81+
flex-wrap: wrap;
82+
align-items: baseline;
83+
gap: 0.5rem;
84+
margin-bottom: 0.25rem;
85+
}
86+
87+
.archive-entry-title {
88+
margin: 0;
89+
font-weight: 500;
90+
font-size: 1.05em;
91+
line-height: 1.3;
92+
}
93+
94+
.archive-entry-link {
95+
color: var(--primary);
96+
text-decoration: none;
97+
}
98+
99+
.archive-entry-link:hover {
100+
color: var(--secondary);
101+
}
102+
103+
/* Series badge */
104+
.archive-series-badge {
105+
display: inline-block;
106+
padding: 0.1rem 0.5rem;
107+
font-size: 0.78em;
108+
color: var(--secondary);
109+
background: rgba(150, 150, 150, 0.12);
110+
border: 1px solid var(--border);
111+
border-radius: 999px;
112+
text-decoration: none;
113+
white-space: nowrap;
114+
}
115+
116+
.archive-series-badge:hover {
117+
color: var(--theme);
118+
background: var(--secondary);
119+
border-color: var(--secondary);
120+
}
121+
122+
/* NEW badge (also rendered server-side for non-JS users; CSS stays for both) */
123+
.archive-new-badge {
124+
display: inline-block;
125+
padding: 0.1rem 0.5rem;
126+
font-size: 0.7em;
127+
font-weight: 700;
128+
color: #fff;
129+
background: linear-gradient(135deg, #06b6d4, #8b5cf6);
130+
border-radius: 4px;
131+
letter-spacing: 0.05em;
132+
vertical-align: middle;
133+
}
134+
135+
/* Excerpt preview */
136+
.archive-excerpt {
137+
margin: 0.3rem 0 0.4rem;
138+
color: var(--secondary);
139+
font-size: 0.9em;
140+
line-height: 1.5;
141+
opacity: 0.85;
142+
}
143+
144+
/* Meta line: keep PaperMod's post_meta, add chips after */
145+
.archive-meta {
146+
display: flex;
147+
flex-wrap: wrap;
148+
align-items: center;
149+
gap: 0.3rem;
150+
color: var(--secondary);
151+
font-size: 0.82em;
152+
}
153+
154+
/* Chips: category + tag */
155+
.archive-chip {
156+
display: inline-block;
157+
padding: 0.1rem 0.5rem;
158+
font-size: 0.85em;
159+
border-radius: 4px;
160+
white-space: nowrap;
161+
}
162+
163+
.archive-chip--cat {
164+
background: rgba(150, 150, 150, 0.15);
165+
color: var(--primary);
166+
font-weight: 500;
167+
}
168+
169+
.archive-chip--tag {
170+
color: var(--secondary);
171+
font-size: 0.8em;
172+
opacity: 0.75;
173+
}
174+
175+
/* Category → border color. Matches tags-rainbow.css palette. */
176+
.archive-entry--cat-随笔 { border-left-color: #f59e0b; } /* amber */
177+
.archive-entry--cat-工具 { border-left-color: #06b6d4; } /* cyan */
178+
.archive-entry--cat-技术 { border-left-color: #8b5cf6; } /* violet */
179+
.archive-entry--cat-uncategorized { border-left-color: var(--border); }
180+
181+
/* Match chip background to category color (subtle tint) */
182+
.archive-entry--cat-随笔 .archive-chip--cat { background: rgba(245, 158, 11, 0.15); }
183+
.archive-entry--cat-工具 .archive-chip--cat { background: rgba(6, 182, 212, 0.15); }
184+
.archive-entry--cat-技术 .archive-chip--cat { background: rgba(139, 92, 246, 0.15); }
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/* ===== Archive page — Tier 2 =====
2+
Pure-CSS category filter pills + compact/detailed view toggle.
3+
No JavaScript — uses :checked sibling selectors.
4+
*/
5+
6+
/* Hide the radio inputs themselves (they only exist to be targets for labels). */
7+
.archive-radio {
8+
position: absolute;
9+
opacity: 0;
10+
pointer-events: none;
11+
width: 0;
12+
height: 0;
13+
}
14+
15+
/* Toolbar layout */
16+
.archive-toolbar {
17+
display: flex;
18+
flex-wrap: wrap;
19+
gap: 1rem 1.5rem;
20+
align-items: center;
21+
justify-content: space-between;
22+
margin: 1rem 0 1.5rem;
23+
padding: 0.6rem 0.8rem;
24+
border: 1px solid var(--border);
25+
border-radius: var(--radius, 8px);
26+
background: var(--entry);
27+
}
28+
29+
.archive-cat-filter,
30+
.archive-view-toggle {
31+
display: flex;
32+
flex-wrap: wrap;
33+
gap: 0.35rem;
34+
align-items: center;
35+
}
36+
37+
/* Pill base style */
38+
.archive-pill {
39+
display: inline-flex;
40+
align-items: center;
41+
padding: 0.3rem 0.85rem;
42+
font-size: 0.85em;
43+
font-weight: 500;
44+
color: var(--secondary);
45+
background: transparent;
46+
border: 1px solid var(--border);
47+
border-radius: 999px;
48+
cursor: pointer;
49+
user-select: none;
50+
transition: all 0.15s ease;
51+
}
52+
53+
.archive-pill:hover {
54+
color: var(--primary);
55+
border-color: var(--secondary);
56+
}
57+
58+
/* Active state via :checked sibling selectors.
59+
The toolbar's pills (label.archive-pill) come AFTER their corresponding
60+
radio (input.archive-radio) in the DOM, so #id:checked ~ .archive-toolbar
61+
chain reaches them. */
62+
63+
/* Per-category filter active states. */
64+
#archive-cat-all:checked ~ .archive-toolbar label[for="archive-cat-all"] {
65+
color: #fff;
66+
background: var(--secondary);
67+
border-color: var(--secondary);
68+
}
69+
70+
/* Generated-style rule: each non-"all" category radio selects its own pill.
71+
We can't loop in CSS, so we list known categories explicitly. */
72+
#archive-cat-随笔:checked ~ .archive-toolbar label[for="archive-cat-随笔"],
73+
#archive-cat-工具:checked ~ .archive-toolbar label[for="archive-cat-工具"],
74+
#archive-cat-技术:checked ~ .archive-toolbar label[for="archive-cat-技术"] {
75+
color: #fff;
76+
background: var(--secondary);
77+
border-color: var(--secondary);
78+
}
79+
80+
/* When a specific category is selected, hide posts that aren't in it. */
81+
.archive-radio[id^="archive-cat-"]:checked ~ .archive-list .archive-entry {
82+
display: none;
83+
}
84+
#archive-cat-随笔:checked ~ .archive-list .archive-entry--cat-随笔,
85+
#archive-cat-工具:checked ~ .archive-list .archive-entry--cat-工具,
86+
#archive-cat-技术:checked ~ .archive-list .archive-entry--cat-技术 {
87+
display: block;
88+
}
89+
90+
/* Hide empty year/month groups when their children are all hidden.
91+
CSS doesn't easily check for "all children hidden", so we just hide
92+
the headers when no matching entry exists within. */
93+
#archive-cat-随笔:checked ~ .archive-list .archive-month:not(:has(.archive-entry--cat-随笔)),
94+
#archive-cat-工具:checked ~ .archive-list .archive-month:not(:has(.archive-entry--cat-工具)),
95+
#archive-cat-技术:checked ~ .archive-list .archive-month:not(:has(.archive-entry--cat-技术)) {
96+
display: none;
97+
}
98+
#archive-cat-随笔:checked ~ .archive-list .archive-year:not(:has(.archive-month)),
99+
#archive-cat-工具:checked ~ .archive-list .archive-year:not(:has(.archive-month)),
100+
#archive-cat-技术:checked ~ .archive-list .archive-year:not(:has(.archive-month)) {
101+
display: none;
102+
}
103+
104+
/* View toggle: detailed (default) shows excerpt + chips; compact hides them. */
105+
.archive-radio[id^="archive-view-"]:checked ~ .archive-toolbar .archive-pill--view {
106+
color: var(--secondary);
107+
}
108+
109+
#archive-view-detailed:checked ~ .archive-toolbar label[for="archive-view-detailed"],
110+
#archive-view-compact:checked ~ .archive-toolbar label[for="archive-view-compact"] {
111+
color: #fff;
112+
background: var(--secondary);
113+
border-color: var(--secondary);
114+
}
115+
116+
/* Compact mode: hide excerpt and meta chips. */
117+
#archive-view-compact:checked ~ .archive-list .archive-excerpt,
118+
#archive-view-compact:checked ~ .archive-list .archive-meta {
119+
display: none;
120+
}
121+
122+
#archive-view-compact:checked ~ .archive-list .archive-entry {
123+
padding: 0.4rem 0.8rem;
124+
margin: 0.3rem 0;
125+
}
126+
127+
#archive-view-compact:checked ~ .archive-list .archive-entry-title {
128+
font-size: 0.98em;
129+
}
130+
131+
/* When JS is disabled, show the count of hidden posts (best-effort fallback).
132+
For now we just hide "no results" — JS in tier 3 will toggle this properly. */
133+
#archive-no-results {
134+
display: none;
135+
padding: 1rem;
136+
text-align: center;
137+
color: var(--secondary);
138+
font-style: italic;
139+
}

0 commit comments

Comments
 (0)