2323 </ head >
2424 < body class ="bg-white text-gray-800 dark:bg-neutral-800 ">
2525 {% include nav.html %}
26+ < section class ="container mx-auto px-4 mt-6 mb-4 ">
27+ < div id ="label-buttons " class ="flex flex-wrap gap-2 ">
28+ < button
29+ class ="label-btn active text-sm bg-amber-400 text-amber-400 bg-opacity-20 font-medium px-3 py-1 rounded-lg "
30+ data-label ="all "
31+ >
32+ All
33+ </ button >
34+ {% assign all_labels = "" | split: "," %} {% for post in site.posts %}
35+ {% for label in post.label %} {% unless all_labels contains label %} {%
36+ assign all_labels = all_labels | push: label %} {% endunless %} {%
37+ endfor %} {% endfor %} {% assign sorted_labels = all_labels | uniq |
38+ sort %} {% for label in sorted_labels %}
39+ < button
40+ class ="label-btn text-sm bg-amber-400 text-amber-400 bg-opacity-10 hover:bg-opacity-20 px-3 py-1 rounded-lg transition "
41+ data-label ="{{ label | downcase }} "
42+ >
43+ #{{ label }}
44+ </ button >
45+ {% endfor %}
46+ </ div >
47+ </ section >
48+
2649 < main class ="container mx-auto px-4 py-6 ">
2750 < section >
28- < h2 class ="text-xl dark:text-neutral-100 font-semibold mb-4 ">
51+ < h2 class ="text-4xl dark:text-neutral-100 font-semibold mb-4 ">
2952 Latest Articles
3053 </ h2 >
3154
@@ -34,45 +57,57 @@ <h2 class="text-xl dark:text-neutral-100 font-semibold mb-4">
3457 {% assign displayed_posts = "" | split: "," %} {% for post in
3558 site.posts limit:1 %} {% unless displayed_posts contains post.url %}
3659 {% assign displayed_posts = displayed_posts | push: post.url %}
60+
3761 < a
3862 href ="{{ post.url }} "
39- class ="rounded-xl hover:bg-neutral-100 dark:hover:bg-neutral-700 p-4 flex flex-col sm:flex-row gap-4 "
63+ class ="rounded-xl hover:bg-neutral-100 dark:hover:bg-neutral-700 p-4 flex flex-col sm:flex-row gap-6 "
4064 >
41- <!-- Uniform height + crop with object-cover -->
65+ <!-- Image -->
4266 < img
4367 src ="{{ post.image }} "
4468 alt ="{{ post.title }} "
45- class ="w-full sm:w-2/3 h-1/3 object-cover object-center rounded-lg "
69+ class ="w-full sm:w-2/3 h-64 sm:h-auto object-cover object-center rounded-lg flex-shrink-0 "
4670 />
47- < div class ="content-center space-y-2 sm:flex-1 ">
48- < h3 class ="text-4xl dark:text-neutral-100 font-bold ">
49- {{ post.title }}
50- </ h3 >
51- < div class ="flex flex-wrap gap-2 py-2 ">
52- {% for label in post.label %}
53- < p
54- class ="text-sm bg-amber-400 text-amber-400 bg-opacity-10 px-2 py-1 rounded-lg "
55- >
56- #{{ label }}
71+
72+ <!-- Content -->
73+ < div class ="flex flex-col justify-between sm:flex-1 space-y-4 ">
74+ < div >
75+ < h3 class ="text-3xl dark:text-neutral-100 font-bold mb-2 ">
76+ {{ post.title }}
77+ </ h3 >
78+
79+ <!-- Labels -->
80+ < div class ="flex flex-wrap gap-2 mb-3 ">
81+ {% for label in post.label %}
82+ < p
83+ class ="text-sm bg-amber-400 text-amber-400 bg-opacity-10 px-2 py-1 rounded-lg "
84+ >
85+ #{{ label }}
86+ </ p >
87+ {% endfor %}
88+ </ div >
89+
90+ <!-- Excerpt -->
91+ < p class ="text-sm dark:text-neutral-100 leading-relaxed ">
92+ {{ post.excerpt | strip_html }}
5793 </ p >
58- {% endfor %}
5994 </ div >
60- < p class ="text-sm dark:text-neutral-100 ">
61- {{ post.excerpt | strip_html }}
62- </ p >
63- < div class ="flex items-center gap-3 dark:text-neutral-100 pt-2 ">
64- < div class ="w-8 h-8 rounded-full overflow-hidden ">
95+
96+ <!-- Author + Date -->
97+ < div
98+ class ="flex items-center gap-3 "
99+ >
100+ < div class ="w-10 h-10 rounded-full overflow-hidden ">
65101 {% include avatar.html %}
66102 </ div >
67103 < div >
68- < p class ="text-sm dark:text-neutral-300 "> {{ post.author }}</ p >
69- < p class ="text-sm text-gray-500 dark:text-neutral-300 ">
70- {{ post.date | date: "%B %d, %Y" }} •
71- < span class ="read-time " title ="Estimated read time ">
72- {% assign words = post.content | strip_html |
73- number_of_words %} {{ words | divided_by: 200 | plus: 1 }}
74- min read
75- </ span >
104+ < p class ="text-sm dark:text-neutral-300 font-medium ">
105+ {{ post.author }}
106+ </ p >
107+ < p class ="text-xs text-gray-500 dark:text-neutral-400 ">
108+ {{ post.date | date: "%B %d, %Y" }} • {% assign words =
109+ post.content | strip_html | number_of_words %} {{ words |
110+ divided_by: 200 | plus: 1 }} min read
76111 </ p >
77112 </ div >
78113 </ div >
@@ -183,5 +218,38 @@ <h3 class="text-2xl dark:text-neutral-100 font-bold">
183218 </ section >
184219 </ main >
185220 {% include footer.html %}
221+ < script >
222+ document . addEventListener ( "DOMContentLoaded" , function ( ) {
223+ const buttons = document . querySelectorAll ( ".label-btn" ) ;
224+ const posts = document . querySelectorAll (
225+ "#post-container a, .grid a, main > section > div > a"
226+ ) ;
227+
228+ buttons . forEach ( ( btn ) => {
229+ btn . addEventListener ( "click" , ( ) => {
230+ // remove active state from others
231+ buttons . forEach ( ( b ) => b . classList . remove ( "bg-opacity-20" ) ) ;
232+ buttons . forEach ( ( b ) => b . classList . add ( "bg-opacity-10" ) ) ;
233+
234+ // activate this one
235+ btn . classList . remove ( "bg-opacity-10" ) ;
236+ btn . classList . add ( "bg-opacity-20" ) ;
237+
238+ const label = btn . dataset . label . toLowerCase ( ) ;
239+
240+ posts . forEach ( ( post ) => {
241+ const labels = Array . from ( post . querySelectorAll ( "p" ) ) . map ( ( el ) =>
242+ el . textContent . toLowerCase ( )
243+ ) ;
244+ if ( label === "all" || labels . some ( ( l ) => l . includes ( label ) ) ) {
245+ post . style . display = "" ;
246+ } else {
247+ post . style . display = "none" ;
248+ }
249+ } ) ;
250+ } ) ;
251+ } ) ;
252+ } ) ;
253+ </ script >
186254 </ body >
187255</ html >
0 commit comments