Menjelang akhir tahun, gue mulai lanjutin lagi proses revamp blog ini. Dari catatan pribadi, revamp ini udah masuk yang ke-9, tapi disini gue rangkum aja bagian majornya biar lebih gampang. Jadi gue anggap ini revamp kedua.
Di revamp yang pertama, gue banyak otak-atik di bagian UI, nah di revamp kedua ini, gue lebih condong ke UXnya, khususnya untuk bagian navigasi.
Search in Navbar
Di PaperMod (tema bawaan), fitur pencariannya ini berupa sebuah halaman khusus. Jadi ketika user mau cari sesuatu di blog gue, dia harus mengklik menu “Search” yang mengarah ke halaman khusus berisi search box. Di situlah tempat user melakukan pencariannya.
Menurut gue hal cara tersebut kurang praktis dan efisien. Jadi, untuk mempermudah navigasi pencarian, gue pindahkan search box tersebut ke bagian Navbar.

Implementasi
Caranya gampang, code html terkait search box tinggal di copy-paste ke dalam layout/partials/header.html:
...[SNIP]...
<div id="searchBox">
<input class="searchInput" id="searchInput" aria-label="search" type="search" placeholder="Search...">
<div class="searchResults-container ">
<span class="search-results hidden" id="searchResults" aria-label="search results" ></span>
</div>
</div>
...[SNIP]...
Fitur search PaperMod ini mengandalkan Fuse dimana index searchnya hanya di-fetch dan dimuat ketika kita berada di halaman search tadi. Artinya, kalau search box gue pindah ke navbar, search-nya nggak akan jalan kecuali indexnya dimuat di setiap halaman.
Untuk hal ini cukup simple, gue cuma perlu hapus kondisional if berikut yang ada di dalam layout/partials/head.html:
{{- /* Search */}}
{{/* Load search in every page */}}
{{- /*if (eq .Layout `search`) */ -}}
<link crossorigin="anonymous" rel="preload" as="fetch" href="{{- .Site.BaseURL -}}index.json">
...[SNIP]...
<script defer crossorigin="anonymous" src="{{ $search.RelPermalink }}"></script>
{{- end }}
{{- /* end */ -}}
Touch up: Add blur effect
Terinspirasi dari tema LoveIt, gue tambahkan juga efek blur ketika user sedang fokus ke pencarian.
Implementasinya juga gampang. Jadi setelah tag <body> (/layouts/_default/baseof.html), gue tambahkan sebuah element div yang berfungsi sebagai masking.
<body>
...[SNIP]...
<div id="mask"></div>
...[SNIP]...
Untuk CSSnya:
#mask {
background-repeat: no-repeat;
background-position: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background-color: rgba(0, 0, 0, 0);
}
body.blur > :not(.header) {
-webkit-filter: blur(4px);
-moz-filter: blur(4px);
-ms-filter: blur(4px);
-o-filter: blur(4px);
filter: blur(4px);
}
Lalu behaviornya gue tambah di JS-nya assets/js/fastsearch.js:
...[SNIP]...
const mask = document.getElementById("mask")
const pageBody = document.body;
function bgBlur() {
pageBody.classList.add("blur");
mask.style.zIndex = "99"; // z-index shouldn't be higher than the navbar/header
mask.style.backgroundColor = "rgba(0,0,0,0.25)";
}
function bgUnblur() {
pageBody.classList.remove("blur");
mask.style.zIndex = "-1";
mask.style.backgroundColor = "rgba(0,0,0,0)";
}
function reset() {
...[SNIP]...
bgUnblur();
}
searchInput.addEventListener("click", bgBlur);
mask.addEventListener("click", reset);
document.addEventListener("click", (e) => {
const item = e.target.closest(".search-item");
if (item) reset();
});
Setelah itu, gue tinggal ngurus stylenya aja supaya search box dan hasil searchnya rapi sekaligus ngga tabrakan dengan menu navbar.
ToC ScrollSpy
Gue balik lagi ngotak-ngatik bagian floating ToC yang sebelumnya udah gue bahas di revamp part satu. Kali ini, floating tocnya punya kemampuan mirip ScrollSpy dari Bootstrap. Singkatnya, ini fitur yang nge-highlight otomatis bagian item ToC mana yang sedang kita lihat atau baca berdasarkan posisi scroll.
Implementasi
Untuk ini, bagian code ToC bawaan dari PaperMod yang sebelumnya cuma buat expand heading ToC aja, gue rombak penuh pakai bantuan ChatGPT. Karena codenya lumayan panjang, jadi gue simpen di gist aja deh.
Swup for Dynamic Page Load
Sebelumnya sempat mikir untuk pindah ke Gatsby atau NextJS yang punya SSR (Server-side rendering), simply cuma pengen transisi perhalamannya lebih seamless dan modern aja sih. Tapi gue urungkan, soalnya Hugo lebih friendly dan gampang dimanage.
Sekarang keinginan untuk punya transisi halaman secara seamless di Hugo ini bisa terwujud berkat Swup. Singkatnya, meskipun gue pakai SSG seperti Hugo, Swup ini bisa ngasih pengalaman mirip SSR.
Implementasi
Untuk implementasinya sendiri cukup mudah kok. Gue cuma perlu nentuin kontainer mana yang mau dijadiin sebagai area konten dinamiknya. Kontainer area konten gue disini adalah element <main>, lalu tinggal tag aja element ini dengan id #swup (/layouts/_default/baseof.html):
...[SNIP]...
<main id="swup" class="main transition-fades
<div class="content-wrapper">
{{- block "main" . }}{{ end }}
</div>
</main>
...[SNIP]...
Masalahnya disini adalah Swup hanya mengupdate element yang ada di dalam kontainer Swup (partial load). Element lain, termasuk script event listener, diluar kontainer Swup, ngga akan ‘aware’ sama partial load dari Swup ini. Karena hal ini, script event listener menganggap element yang ditempel (attach) di dalam kontainer itu jadi hilang/null. Akibatnya, beberapa event ngga akan jalan.
Buat masalah ini, solusinya adalah melakukan reinisialasi kembali semua event listener atau script dari element yang ada di dalam kontainer Swup setiap kali partial load terjadi.
custom.js:
const swup = new Swup();
function initCustomFunction() {
initTOC(".toc");
profileClick(".profile-img");
restoreMenuScroll();
updateActiveMenu();
hljs.highlightAll();
}
// first init custom listeners
document.addEventListener("DOMContentLoaded", () => {
initCustomFunction();
});
// reinit on page ready
swup.hooks.on("page:view", () => {
initCustomFunction();
});
End
Baiklah, kurang lebih itu update revamp kali ini dan gue udah ngerasa cukup puaslah, terutama dibagian Swup. Soal revamp ini juga itung-itung refreshing skill web sih, jadi bakal gue lanjut di part berikutnya untuk bagian mobile (mungkin).
See you!