Replace pagination with infinite scroll for blog list

This commit is contained in:
2026-05-14 01:19:43 +08:00
parent 520206f391
commit 2e2f0c9c6f
2 changed files with 89 additions and 31 deletions
+1 -1
View File
@@ -20,7 +20,7 @@
Hey, I'm FuKun. Hey, I'm FuKun.
Solo developer. Ex-product manager. State-owned enterprise manager. New dad. Most of my waking hours go to my career — I've done IT operations automation at scale, built billing systems handling massive transaction volumes, architected security for enormous resource pools, and untangled enterprise identity governance. It's been fun. Solo developer. Ex-product manager. China state-owned enterprise manager. New dad. Most of my waking hours go to my career — I've done IT operations automation at scale, built billing systems handling massive transaction volumes, architected security for enormous resource pools, and untangled enterprise identity governance. It's been fun.
This site isn't about methodology or technique. It's about the **self** that should sit above all the roles we play. I think people struggle to admit how much their identity gets defined by their roles — and yet, no identity you've held has lasted more than five years since birth. When emotions hit, you still react the same way you did at five. This site isn't about methodology or technique. It's about the **self** that should sit above all the roles we play. I think people struggle to admit how much their identity gets defined by their roles — and yet, no identity you've held has lasted more than five years since birth. When emotions hit, you still react the same way you did at five.
+78 -20
View File
@@ -1,34 +1,92 @@
{{ define "main" }} {{ define "main" }}
<div class="hx:mx-auto hx:flex hextra-max-page-width"> <div class="hx:mx-auto hx:flex hextra-max-page-width">
{{ partial "sidebar.html" (dict "context" . "disableSidebar" true "displayPlaceholder" true) }} {{ partial "sidebar.html" (dict "context" . "disableSidebar" true
<article class="hx:w-full hx:break-words hx:flex hx:min-h-[calc(100vh-var(--navbar-height))] hx:min-w-0 hx:justify-center hx:pb-8 hx:pr-[calc(env(safe-area-inset-right)-1.5rem)]"> "displayPlaceholder" true) }}
<main id="content" class="hx:w-full hx:min-w-0 hextra-max-content-width hx:px-6 hx:pt-4 hx:md:px-12"> <article
class="hx:w-full hx:break-words hx:flex hx:min-h-[calc(100vh-var(--navbar-height))] hx:min-w-0 hx:justify-center hx:pb-8 hx:pr-[calc(env(safe-area-inset-right)-1.5rem)]"
>
<main
id="content"
class="hx:w-full hx:min-w-0 hextra-max-content-width hx:px-6 hx:pt-0 hx:md:px-12"
>
{{ partial "breadcrumb.html" (dict "page" . "enable" false) }} {{ partial "breadcrumb.html" (dict "page" . "enable" false) }}
<br class="hx:mt-1.5 hx:text-sm" /> <br class="hx:mt-1.5 hx:text-sm" />
<div class="content">{{ .Content }}</div> <div class="content">{{ .Content }}</div>
{{- $pages := partial "utils/sort-pages" (dict "page" . "by" site.Params.blog.list.sortBy "order" site.Params.blog.list.sortOrder) -}}
{{- $pagerSize := site.Params.blog.list.pagerSize | default 10 -}} {{- $pages := partial "utils/sort-pages" (dict "page" . "by"
{{- $paginator := .Paginate $pages $pagerSize -}} site.Params.blog.list.sortBy "order"
{{- range $paginator.Pages }} site.Params.blog.list.sortOrder) -}} {{- $batch :=
<div class="hx:mb-10"> site.Params.blog.list.pagerSize | default 10 }} {{- $total := len
<h3><a style="color: inherit; text-decoration: none;" class="hx:block hx:font-semibold hx:mt-8 hx:text-2xl" href="{{ .RelPermalink }}">{{ .Title }}</a></h3> $pages }}
<p class="hx:opacity-50 hx:text-sm hx:mt-1 hx:leading-7">{{ partial "utils/format-date" .Date }}</p>
<div id="post-list">
{{- range $i, $p := $pages }}
<div
class="hx:mb-10 blog-post-item{{ if ge $i $batch }} hx:hidden{{ end }}"
data-index="{{ $i }}"
>
<h3>
<a
style="color: inherit; text-decoration: none"
class="hx:block hx:font-semibold hx:mt-8 hx:text-2xl"
href="{{ $p.RelPermalink }}"
>{{ $p.Title }}</a
>
</h3>
<p class="hx:opacity-50 hx:text-sm hx:mt-1 hx:leading-7">
{{ partial "utils/format-date" $p.Date }}
</p>
{{ if site.Params.blog.list.displayTags }} {{ if site.Params.blog.list.displayTags }}
<div class="hx:text-sm hx:leading-7"> <div class="hx:text-sm hx:leading-7">
{{ partial "tags.html" (dict "context" .) }} {{ partial "tags.html" (dict "context" $p) }}
</div> </div>
{{ end }} {{ end }}
<a href="{{ .RelPermalink }}" style="color: inherit; text-decoration: none;"> <a
<p class="hx:opacity-80 hx:mt-2 hx:leading-7">{{- partial "utils/page-description" . -}}</p> href="{{ $p.RelPermalink }}"
style="color: inherit; text-decoration: none"
>
<p class="hx:opacity-80 hx:mt-2 hx:leading-7">
{{- partial "utils/page-description" $p -}}
</p>
</a> </a>
</div> </div>
{{ end -}} {{- end }}
</div>
{{- if gt $paginator.TotalPages 1 -}} {{- if gt $total $batch }}
{{ partial "components/blog-pager.html" $paginator }} <div id="load-more-trigger" class="hx:h-4"></div>
{{- end -}} {{- end }}
</main> </main>
</article> </article>
<div class="hx:max-xl:hidden hx:h-0 hx:w-64 hx:shrink-0"></div> <div class="hx:max-xl:hidden hx:h-0 hx:w-64 hx:shrink-0"></div>
</div> </div>
{{- end -}}
{{- if gt $total $batch }}
<script>
(function () {
var batch = {{ $batch }};
var total = {{ $total }};
var visible = batch;
var items = document.querySelectorAll('.blog-post-item');
var trigger = document.getElementById('load-more-trigger');
if (!trigger) return;
function showNext() {
var next = Math.min(visible + batch, total);
for (var i = visible; i < next; i++) {
items[i].classList.remove('hx:hidden');
}
visible = next;
if (visible >= total) {
trigger.remove();
}
}
var observer = new IntersectionObserver(function (entries) {
if (entries[0].isIntersecting) showNext();
}, { rootMargin: '200px' });
observer.observe(trigger);
})();
</script>
{{- end }} {{- end }}