Daftar Isi
Sudah bukan zamannya lagi konten blog itu statis, flat, dan membosankan. Di era di mana attention span manusia makin pendek dan ekspektasi visual makin tinggi, kamu butuh sesuatu yang lebih dari sekadar artikel biasa. Kamu butuh WebStory by Han Haoyu — sebuah story engine interaktif yang hadir bukan untuk ikut-ikutan trend, tapi untuk mendefinisikan ulang bagaimana konten web seharusnya dinikmati.
Dibangun dari nol oleh Han Haoyu — seorang developer yang nggak pernah puas sama solusi setengah jadi — WebStory by HHC adalah hasil dari ratusan jam riset, eksperimen UI/UX, dan obsesi terhadap detail terkecil. Setiap pixel, setiap animasi, setiap transisi: semua disengaja. Semua punya tujuan. Dan hasilnya? Sesuatu yang belum pernah ada sebelumnya di dunia Blogger.
Kenapa WebStory by HHC Beda Level?
Sebelum masuk ke detail fitur, kamu perlu paham dulu mengapa WebStory by HHC bukan widget story biasa. Ada beberapa hal fundamental yang membuatnya stand out dari semua solusi story yang pernah ada di ekosistem Blogger:
100% Vanilla JavaScript. Tidak ada jQuery. Tidak ada React. Tidak ada library eksternal apapun. WebStory by HHC berjalan dengan pure JS yang ditulis langsung dari scratch — artinya tidak ada overhead, tidak ada dependency hell, dan tidak ada risiko breaking change dari library pihak ketiga.
Bandingkan dengan solusi lain yang biasanya require beberapa library sekaligus dan total bundle size bisa mencapai ratusan KB. WebStory by HHC? Satu file. Bersih. Efisien.
Design system yang kohesif dan konsisten. Setiap elemen visual — dari warna, spacing, typography, hingga animasi — menggunakan CSS Custom Properties yang terdefinisi di satu tempat (:root). Ini berarti setiap perubahan warna brand bisa dilakukan dalam satu baris CSS dan langsung propagate ke seluruh UI.
Color palette yang dipakai — #00c49a sebagai accent dan dark green sebagai base — bukan pilihan random. Ini adalah palette yang didesain untuk contrast ratio tinggi di dark background, readable di semua kondisi cahaya.
Performa yang diobsesikan. Semua gambar dalam story menggunakan loading="lazy" kecuali gambar pertama yang pakai loading="eager". Slide yang tidak aktif tidak di-render ulang — hanya ditransform via CSS untuk menghemat memory. Video menggunakan preload="none" sampai benar-benar dibutuhkan.
Animasi 100% berbasis CSS transforms dan opacity — tidak ada layout thrashing, tidak ada repaints yang mahal. Semua element yang di-animate menggunakan will-change: transform, opacity untuk GPU acceleration.
IndexedDB caching yang intelligent. Story data — terutama blog feed yang di-fetch dari internet — di-cache langsung di browser user. Load pertama mungkin butuh network request, tapi load kedua dan seterusnya? Instant. Zero network request. Zero latency.
Cache memiliki TTL (Time To Live) yang berbeda per tipe content: blog feed cache 10 menit, static story cache tidak expire. Background refresh bekerja diam-diam tanpa mengganggu experience user.
Perbandingan: WebStory HHC vs Solusi Story Lainnya
| Fitur | WebStory HHC | Plugin Story Biasa | Instagram Stories Embed |
|---|---|---|---|
| Vanilla JS (no library) | ✅ Ya | ❌ Butuh jQuery/React | ❌ Iframe based |
| Music Player Built-in | ✅ Full featured | ❌ Tidak ada | ❌ Tidak ada |
| Blog Feed Otomatis | ✅ Blogger JSON API | ⚠️ Manual input | ❌ Tidak relevan |
| IndexedDB Caching | ✅ Intelligent TTL | ❌ Tidak ada | ❌ Tidak ada |
| Horizontal Drag Slider | ✅ Touch + Mouse | ⚠️ Tergantung plugin | ❌ Tidak ada |
| Cross-Story Navigation | ✅ Auto pindah story | ❌ Tidak ada | ❌ Tidak ada |
| Sponsored Story Mode | ✅ Badge otomatis | ❌ Tidak ada | ⚠️ Manual label |
| End Screen Smart | ✅ Context-aware | ❌ Tidak ada | ❌ Tidak ada |
| Keyboard Navigation | ✅ Arrow + Esc | ⚠️ Jarang ada | ❌ Tidak ada |
*Data perbandingan berdasarkan fitur umum yang tersedia di pasaran. Bisa berubah seiring update masing-masing produk.
Live Demo — Lihat Sendiri Kerennya
Nggak ada yang lebih meyakinkan dari melihat langsung. Di bawah ini adalah video demo full walkthrough WebStory by HHC — dari circle story, berbagai tipe page, music player, blog feed, sampai end screen. Tonton sampai habis!
Demo video sedang dalam proses produksi. Kamu bisa langsung mencoba fiturnya di live demo yang ada di halaman utama hanhaoyu.com.
UI/UX Design — Setiap Pixel Ada Alasannya
WebStory by HHC bukan sekadar "bikin widget yang jalan". Ini adalah sebuah design system yang dipikirkan matang dari level paling dalam. Mari kita bedah satu per satu.
1. Overlay System & Backdrop Blur
Saat story dibuka, seluruh halaman web di-cover oleh overlay semi-transparan dengan efek backdrop-filter: blur(10px). Ini bukan pilihan estetik semata — ada alasan UX-nya:
- ✔ Focus isolation — user secara visual "meninggalkan" halaman dan masuk ke mode story. Cognitive load berkurang karena background halaman tidak lagi competing for attention.
- ✔ Depth perception — blur menciptakan efek depth yang memberikan kesan bahwa story "mengambang" di atas halaman, bukan menimpa flat.
- ✔ Graceful degradation — kalau browser tidak support
backdrop-filter, overlay tetap berfungsi dengan background solidrgba(0,0,0,.84).
.ws-oWebStorybyHHC {
position: fixed;
inset: 0;
z-index: 99999; /* Selalu di atas segalanya */
display: none;
align-items: center;
justify-content: center;
background: rgba(0,0,0,.84);
backdrop-filter: blur(10px); /* Blur efek */
-webkit-backdrop-filter: blur(10px); /* Safari prefix */
}
.ws-oWebStorybyHHC.onWebStorybyHHC {
display: flex; /* Aktif saat class .on ditambahkan via JS */
}
/* Kenapa z-index: 99999? */
/* Blogger theme banyak yang punya header sticky
dengan z-index tinggi. 99999 memastikan story
selalu di atas semua element tema, termasuk
header, modal, atau widget lainnya. */
/* Kenapa inset: 0? */
/* Shorthand modern untuk
top: 0; right: 0; bottom: 0; left: 0;
Lebih ringkas, sama efeknya. */
2. Story Box — Responsive Container
Story container (.ws-bWebStorybyHHC) punya sistem responsive 3 breakpoint yang elegan:
| Breakpoint | Behavior | Alasan UX |
|---|---|---|
< 560px (mobile) |
Full screen, border-radius: 0 |
Di mobile, full screen terasa lebih immersive. Rounded corner di pojok layar kecil justru terlihat aneh. |
≥ 560px (tablet) |
Max height 88vh, border-radius: 20px |
Ada ruang di sekeliling story — context dari halaman tetap visible. Border radius memberikan kesan "card" yang mengambang. |
≥ 900px (desktop) |
Max width dihitung dari min(390px, calc(88vh * 0.56)) |
Rasio 9:16 portrait dipertahankan. Story tidak stretching jadi wide di layar besar — tetap portrait untuk konsistensi dengan format story mobile. |
Formula calc(88vh * 0.56) adalah cara cerdas untuk memastikan story box selalu punya aspek rasio mendekati 9:16 terlepas dari tinggi layar. Karena 9/16 ≈ 0.5625 ≈ 0.56.
3. Dark Background dengan Gradient Mesh
Background story bukan solid hitam — ada gradient mesh subtle yang memberikan kedalaman:
.ws-bWebStorybyHHC::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(160deg, #0d2420, #071510);
/* Diagonal gradient dari hijau tua gelap ke hitam kehijauan */
/* Ini yang bikin background terasa "hidup" meski tidak ada gambar */
z-index: 0;
pointer-events: none; /* Tidak menghalangi klik */
}
Gradient mesh ini yang bikin story terlihat premium bahkan sebelum gambar/konten load. Kalau ada loading state atau slide tanpa background image, halaman tetap terlihat beautiful — bukan blank hitam polos.
4. Grid Texture Overlay
Ada overlay grid texture ultra-subtle di setiap slide (.ws-grWebStorybyHHC) dengan opacity hanya 2.5%. Ini tidak terlihat secara eksplisit tapi memberikan texture depth yang membuat gambar terasa lebih "berdimensi" dan tidak terlalu clean/digital.
.ws-grWebStorybyHHC {
background-image:
linear-gradient(rgba(255,255,255,.6) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,.6) 1px, transparent 1px);
background-size: 36px 36px;
opacity: .025; /* Sangat subtle — hampir tidak terlihat tapi terasa */
}
5. Floating Orb Animation
Ada elemen dekoratif — sebuah radial gradient circle berwarna teal — yang float di pojok kanan atas setiap slide:
.ws-o1WebStorybyHHC {
width: 200px; height: 200px;
border-radius: 50%;
background: radial-gradient(circle, rgba(0,196,154,.2) 0%, transparent 70%);
top: -60px; right: -60px; /* Sebagian tersembunyi di luar frame */
animation: wsFloatWebStorybyHHC 4s ease-in-out infinite;
}
@keyframes wsFloatWebStorybyHHC {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
/* Float naik-turun 8px selama 4 detik, loop infinite */
}
Elemen kecil ini memberikan sense of motion pada slide yang statis — membuat story terasa "bernapas" meski tidak ada animasi konten di dalamnya.
Story Circles — Portal Masuk yang Eye-Catching
Story circles adalah elemen pertama yang dilihat user di halaman kamu. Ini adalah "pintu masuk" ke story — dan desainnya harus cukup menarik untuk di-tap. WebStory HHC mendesain circle ini dengan sangat detail.
Ring Animation — 5 Style Berbeda
Ring/border di sekeliling circle bukan hanya dekoratif — ia berkomunikasi kepada user tentang tipe konten yang ada di dalam story:
Ring Default — Rainbow Gradient (Instagram-style)
.ws-riWebStorybyHHC::before {
/* Menggunakan conic-gradient untuk ring pelangi yang rotate */
background: conic-gradient(
from 0deg,
#f09433, #e6683c, #dc2743, #cc2366,
#bc1888, #833ab4, #5851db, #405de6,
#5851db, #833ab4, #bc1888, #cc2366,
#dc2743, #e6683c, #f09433
);
/* Teknik clip mask untuk membuat ring tanpa elemen tambahan */
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: wsRRWebStorybyHHC 3s linear infinite; /* Rotate 3 detik */
}
mask-composite: exclude ini adalah cara cerdas membuat "donut shape" tanpa perlu dua elemen berbeda. Inner circle di-mask out sehingga hanya border-nya yang terlihat.Ring lv — Live (Merah Pulse, Animasi 2x Lebih Cepat)
.ws-riWebStorybyHHC.lvWebStorybyHHC::before {
background: conic-gradient(from 0deg, #ff4757, #ff6b81, #ff8a94, #ff4757);
animation-duration: 2s; /* Lebih cepat dari default 3s */
/* Kecepatan rotate yang lebih tinggi = sense of urgency untuk LIVE content */
}
.ws-bd-pillWebStorybyHHC.lvWebStorybyHHC {
background: #ff4757; color: #fff;
animation: wsBlinkWebStorybyHHC .9s ease-in-out infinite alternate;
/* Badge LIVE ikut berkedip untuk reinforcing "live" feeling */
}
@keyframes wsBlinkWebStorybyHHC {
from { opacity: 1; }
to { opacity: .35; }
}
Ring sp — Sponsored (Gold)
.ws-riWebStorybyHHC.spWebStorybyHHC::before {
background: conic-gradient(from 0deg, #f5c842, #ffb300, #ffe066, #f5c842);
/* Gold gradient — sinyal visual untuk sponsored/berbayar content */
}
.ws-bd-pillWebStorybyHHC.spWebStorybyHHC {
background: #f5c842; color: #1a1a1a; /* Dark text on gold untuk contrast */
}
Ring nw — New (Teal/Hijau Brand)
.ws-riWebStorybyHHC.nwWebStorybyHHC::before {
background: conic-gradient(from 0deg, #00c49a, #a8f0e0, #00c49a);
/* Warna brand HHC — konsisten dengan color system */
}
Ring mu — Music (Spotify-inspired Green)
.ws-riWebStorybyHHC.muWebStorybyHHC::before {
background: conic-gradient(from 0deg, #1db954, #1ed760, #b3de69, #1db954);
/* Hijau Spotify — instantly recognizable sebagai musik content */
}
Badge Pill Component
Badge kecil di bawah circle adalah micro-communication yang powerful. User bisa tahu tipe konten hanya dari badge tanpa perlu membuka story:
| Badge | Warna | Animasi | Sinyal ke User |
|---|---|---|---|
LIVE | Merah | Berkedip (blink) | "Ada konten real-time/terbaru" |
AD / Sponsored | Emas | Static | "Ini konten berbayar/partner" |
NEW | Teal | Static | "Ada konten baru yang belum kamu lihat" |
Music | Hijau | Static | "Story ini berisi musik/playlist" |
| Custom text | Biru | Static | Label custom sesuai kebutuhan |
Badge LIVE secara khusus mendapat dot merah berkedip di sebelah kiri teksnya — persis seperti indicator live di platform broadcasting. Detail kecil ini bukan kebetulan.
Progress Bar & Header — Navigation Hub
Segmented Progress Bar
Progress bar WebStory HHC bukan satu bar panjang — ia adalah segmented bar di mana setiap segmen mewakili satu slide. Ini memberikan user spatial awareness: mereka tahu ada berapa slide dan sudah di posisi mana.
.ws-pgWebStorybyHHC {
position: absolute;
top: 0; left: 0; right: 0;
z-index: 100; /* Di atas semua konten slide */
display: flex;
gap: 3px; /* Gap 3px antar segment — tipis tapi visible */
padding: 10px 12px 6px;
pointer-events: none; /* Tidak bisa diklik — navigasi via tap zone */
}
.ws-pfWebStorybyHHC.acWebStorybyHHC {
animation: wsBarWebStorybyHHC linear forwards;
/* Linear timing = progress yang konsisten, predictable */
/* 'forwards' = bar tidak kembali ke 0% setelah animasi selesai */
}
@keyframes wsBarWebStorybyHHC {
from { width: 0; }
to { width: 100%; }
/* Durasi ditentukan dari JS: f.style.animationDuration = dur + 'ms' */
}
Fill animation menggunakan linear timing function — bukan ease atau ease-in-out. Ini disengaja: progress yang linear menciptakan ekspektasi yang akurat tentang kapan slide akan berganti.
Brand Header — Identitas yang Selalu Terlihat
Header story menampilkan logo + nama brand + badge konten yang konsisten di setiap slide. User selalu tahu mereka sedang melihat konten dari siapa:
Logo Container dengan Fallback Gradient
.ws-blWebStorybyHHC {
width: 26px; height: 26px;
border-radius: 50%;
background: linear-gradient(135deg, var(--waWebStorybyHHC), var(--wbWebStorybyHHC));
/* Gradient background sebagai fallback kalau image gagal load */
/* User masih melihat colored circle branded, bukan broken image */
display: flex; align-items: center; justify-content: center;
overflow: hidden;
}
Brand Name Marquee — Fitur Tersembunyi yang Keren
Kalau nama brand lebih dari 18 karakter, nama akan otomatis jadi marquee/scrolling text — tidak terpotong, tidak overflow, tapi scroll smooth:
.ws-bnWebStorybyHHC.mqWebStorybyHHC span {
display: inline-block;
white-space: nowrap;
animation: wsMarqWebStorybyHHC 8s linear infinite;
/* Teks di-duplicate dalam HTML: "Nama Panjang Nama Panjang"
Saat animasi selesai dan loop, transisi seamless karena
teks sudah ada di posisi awal */
}
@keyframes wsMarqWebStorybyHHC {
0% { transform: translateX(0); }
40% { transform: translateX(0); } /* Pause di awal 40% durasi */
100% { transform: translateX(-100%); }
}
Slide Counter
Di pojok kanan header ada counter kecil "1 / 7" yang update real-time. Ini adalah aria-live="polite" element — screen reader akan membacakan perubahan ini tanpa mengganggu user yang sedang menggunakan assistive technology.
Header Button Group
Tombol di header (background music, video mute, close) menggunakan backdrop-filter: blur(14px) — sama seperti glass morphism effect. Ini membuat tombol tetap terbaca di atas background apapun tanpa perlu solid background yang menutupi konten.
Tipe-Tipe Slide — 9 Layout, Infinite Possibility
Kekuatan WebStory HHC ada di variasi tipe slidenya. Setiap tipe punya visual identity dan behavior yang unique. Mari kita explore semuanya:
Cover Slide — First Impression Segalanya
Cover slide menggunakan layout ccWebStorybyHHC (center-centered) dengan overflow-y: auto — artinya kalau konten overflow secara teoritis bisa di-scroll, tapi desainnya memastikan konten minimal sehingga tidak perlu scroll.
Elemen visual khas cover: garis horizontal dekoratif (.ws-cvlWebStorybyHHC) — gradient 48px dari teal ke transparent — yang berfungsi sebagai visual separator antara title dan subtitle. Simple tapi impactful.
.ws-cvlWebStorybyHHC {
width: 48px; height: 3px;
background: linear-gradient(90deg, var(--waWebStorybyHHC), transparent);
margin: 10px auto 13px;
/* Fade ke kanan — bukan garis biasa, tapi branded gradient line */
}
Quote Slide — Konten yang Bicara Sendiri
Quote slide adalah slide paling "high impact" secara konten. Box kutipannya menggunakan background rgba(255,255,255,.93) — hampir opaque putih — yang menciptakan contrast dramatis dengan dark background di belakangnya.
Border kiri 4px berwarna teal (border-left: 4px solid var(--waWebStorybyHHC)) adalah sinyal visual standar untuk blockquote yang langsung recognizable oleh user.
Tanda kutip dekoratif (") berukuran 2em dengan line-height 0.4 — ini membuatnya overlap dengan teks di bawahnya secara vertikal, menciptakan efek typographic yang terlihat professional.
Feature Slide — Show, Don't Just Tell
Setiap feature item menggunakan layout flex dengan icon box di kiri dan teks di kanan. Icon box (.ws-ibWebStorybyHHC) adalah square 42px dengan border-radius: 10px dan gradient background teal — memberikan visual weight yang seimbang dengan teks.
Box shadow pada icon (0 0 16px rgba(0,196,154,.25)) menciptakan efek glow subtle yang membuat icon terasa "menyala" — menambah premium feel tanpa berlebihan.
Setiap feature row menggunakan animation delay yang berbeda (d2, d3, d4, d5) sehingga muncul satu per satu secara staggered — bukan sekaligus. Ini membuat user secara alami membaca dari atas ke bawah.
Stats Slide — Numbers yang Hidup
Fitur paling cinematic: animated counter. Saat slide stats aktif, semua angka di-animate dari 0 ke target nilai dengan cubic ease-out:
function animStatsWebStorybyHHC(el) {
el.querySelectorAll('.ws-snWebStorybyHHC[data-target]')
.forEach(function(n) {
var t = parseInt(n.dataset.target) || 0;
var dur = 1400; // 1.4 detik untuk complete counter
var st = performance.now();
(function tick(now) {
var p = Math.min((now - st) / dur, 1);
var ease = 1 - Math.pow(1 - p, 3); // Cubic ease-out
n.textContent = Math.round(ease * t) + '+';
if (p < 1) requestAnimationFrame(tick);
else n.textContent = t + '+';
})(st);
});
}
Formula 1 - Math.pow(1-p, 3) adalah cubic ease-out — angka bertambah cepat di awal, melambat di akhir. Ini terasa natural dan satisfying untuk dilihat.
Horizontal Slider — Touch Native, Drag Friendly
Slider horizontal mendukung dua mode input secara bersamaan: mouse drag dan touch swipe. Logika snap-to-nearest memastikan slider selalu berhenti di posisi item yang clean, tidak nanggung di tengah.
Threshold drag: 40px. Artinya swipe kurang dari 40px tidak trigger perpindahan item — ini mencegah accidental navigation saat user hanya scroll halaman secara vertikal.
Untuk mencegah konflik antara drag slider dan tap zone story, saat user berinteraksi dengan slider, tap zone di-disable via class ws-tap-offWebStorybyHHC. Setelah pointer up, re-enable setelah 120ms delay.
Music Player — Experience, Bukan Sekadar Audio
Music player story terdiri dari dua sub-komponen: track list cover (overview semua lagu) dan player detail (untuk setiap lagu). Auto-advance ke player detail saat item di list diklik, dan auto-play audio dimulai.
Equalizer animation (.ws-eqWebStorybyHHC) — 4 batang beranimasi naik-turun dengan delay berbeda — memberikan visual feedback bahwa musik sedang diputar. Pure CSS, zero JavaScript untuk animasi ini.
Progress bar range input custom: thumb (handle drag) berdiameter 13px dengan box-shadow glow teal. Ini lebih besar dari default browser untuk touch-friendliness tapi tidak terlalu besar secara visual.
Animation System — Gerakan yang Bercerita
WebStory HHC punya animation system yang terdiri dari 3 keyframe utama + staggered delay classes:
@keyframes wsFUWebStorybyHHC {
from { opacity: 0; transform: translateY(22px); }
to { opacity: 1; transform: none; }
}
/* Dipakai untuk: teks, tombol, card konten */
/* translateY(22px) = bergerak dari bawah ke atas */
/* Memberikan kesan konten "naik" ke tempatnya */
.afuWebStorybyHHC {
animation: wsFUWebStorybyHHC .55s cubic-bezier(.4,0,.2,1) both;
}
@keyframes wsFIWebStorybyHHC {
from { opacity: 0; }
to { opacity: 1; }
}
/* Dipakai untuk: elemen yang tidak butuh movement */
/* Pure fade — subtle, tidak distraktif */
.afiWebStorybyHHC {
animation: wsFIWebStorybyHHC .65s ease both;
}
@keyframes wsSIWebStorybyHHC {
from { opacity: 0; transform: scale(.9); }
to { opacity: 1; transform: scale(1); }
}
/* Dipakai untuk: gambar, grid, card container */
/* Scale dari 90% ke 100% + fade = zoom-in subtle */
.asiWebStorybyHHC {
animation: wsSIWebStorybyHHC .5s cubic-bezier(.4,0,.2,1) both;
}
Staggered Delay Classes
Lima delay class untuk membuat elemen muncul secara berurutan — menciptakan choreographed entrance:
| Class | Delay | Dipakai Untuk |
|---|---|---|
d1WebStorybyHHC | 80ms | Elemen pertama setelah bg load (hampir instant) |
d2WebStorybyHHC | 200ms | Elemen kedua |
d3WebStorybyHHC | 330ms | Elemen ketiga |
d4WebStorybyHHC | 480ms | Elemen keempat |
d5WebStorybyHHC | 630ms | Elemen kelima/terakhir |
Slide Transition
Transisi antar slide menggunakan kombinasi translateX dan scale:
.ws-pg-elWebStorybyHHC {
transform: translateX(100%) scale(.97);
/* Slide baru datang dari kanan, sedikit di-scale down */
transition: opacity, transform;
transition-duration: calc(var(--wamWebStorybyHHC) * 1ms); /* 420ms default */
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
/* Material Design standard easing — smooth tapi snappy */
will-change: transform, opacity; /* GPU acceleration hint */
}
.ws-pg-elWebStorybyHHC.prvWebStorybyHHC {
transform: translateX(-100%) scale(.97);
/* Slide lama pergi ke kiri */
}
.ws-pg-elWebStorybyHHC.curWebStorybyHHC {
opacity: 1;
transform: none; /* Posisi normal */
}
Scale 0.97 (bukan 1.0) pada slide yang masuk/keluar memberikan efek depth perspective subtle — seolah slide yang aktif "lebih dekat" ke user dibanding slide yang transisi.
Sistem Interaksi — 5 Input, 1 Experience
WebStory HHC dirancang untuk diakses dengan cara apapun yang user prefer. Semua mode input di-handle secara native tanpa library tambahan.
Tap Zone System — Klik Kiri/Kanan
Dua tap zone transparan menutupi 36% kiri dan 36% kanan dari layar story. Klik/tap di area kiri = prev, area kanan = next.
.ws-tpWebStorybyHHC, .ws-tnWebStorybyHHC {
position: absolute;
top: 60px; /* Tidak overlap dengan progress bar + header */
bottom: 80px; /* Tidak overlap dengan CTA bar */
width: 36%; /* 36% dari lebar story */
z-index: 9;
background: transparent; /* Invisible */
border: none;
-webkit-tap-highlight-color: transparent; /* Hilangkan highlight biru di iOS */
}
.ws-tap-offWebStorybyHHC .ws-tpWebStorybyHHC,
.ws-tap-offWebStorybyHHC .ws-tnWebStorybyHHC {
pointer-events: none; /* Disable saat interaksi dengan scrollable content */
}
Area tengah (28%) sengaja tidak di-cover tap zone — ini area untuk konten scrollable agar user bisa scroll teks panjang tanpa accidentally navigate ke slide lain.
Touch Swipe — Kiri/Kanan dengan Threshold
EWebStorybyHHC.b.addEventListener('touchend', function(ev) {
if (EWebStorybyHHC.b.classList.contains('ws-tap-offWebStorybyHHC')) return;
var dx = ev.changedTouches[0].clientX - _txHHC; // Delta X
var dy = ev.changedTouches[0].clientY - _tyHHC; // Delta Y
if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 44) {
// Horizontal swipe lebih dominan dari vertikal
// Threshold 44px — cukup besar untuk mencegah accidental swipe
if (dx < 0) goNextWebStorybyHHC();
else goPrevWebStorybyHHC();
}
}, {passive: true}); // passive:true untuk scroll performance
Pengecekan Math.abs(dx) > Math.abs(dy) memastikan swipe vertikal (untuk scroll konten) tidak ter-intercept sebagai navigasi horizontal.
Keyboard Navigation — Desktop Power User
document.addEventListener('keydown', function(ev) {
// Hanya aktif saat overlay story terbuka
if (!EWebStorybyHHC.o.classList.contains('onWebStorybyHHC')) return;
if (ev.key === 'ArrowRight') goNextWebStorybyHHC();
else if (ev.key === 'ArrowLeft') goPrevWebStorybyHHC();
else if (ev.key === 'Escape') closeStoryWebStorybyHHC();
});
Guard clause pertama (if (!...onWebStorybyHHC)) sangat penting — tanpa ini, arrow key navigation akan aktif bahkan saat story tidak terbuka, yang bisa conflict dengan behavior halaman normal.
Pause on Hover — Desktop Quality of Life
// Pause timer saat mouse di atas story
EWebStorybyHHC.b.addEventListener('mouseenter', function() {
clearTimeout(SWebStorybyHHC.tim);
});
// Resume timer saat mouse meninggalkan area story
EWebStorybyHHC.b.addEventListener('mouseleave', function() {
if (!EWebStorybyHHC.o.classList.contains('onWebStorybyHHC')) return;
var pg = SWebStorybyHHC.story && SWebStorybyHHC.story.pages[SWebStorybyHHC.cur];
if (!pg) return;
var dur = pg.duration || 0;
// Video, musik, dan end screen tidak auto-resume
if (pg.type === 'video' || pg.video) dur = 0;
if (pg.type === 'music_cover' || pg.type === 'music_player') dur = 0;
if (dur > 0) schedAutoWebStorybyHHC(dur);
});
Visibility API — Pause Saat Tab Tidak Aktif
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
// Tab tidak aktif: pause semua
clearTimeout(SWebStorybyHHC.tim);
if (SWebStorybyHHC.vid) SWebStorybyHHC.vid.pause();
if (SWebStorybyHHC.bgAudio) SWebStorybyHHC.bgAudio.pause();
if (SWebStorybyHHC.mp.audio) SWebStorybyHHC.mp.audio.pause();
} else if (EWebStorybyHHC.o.classList.contains('onWebStorybyHHC')) {
// Tab aktif kembali: resume semua
// ... resume logic
}
});
Ini adalah UX consideration yang sering dilewatkan developer lain. Tanpa Visibility API handling, story akan terus advance meski user berpindah tab — dan saat kembali, konten sudah berubah tanpa user sadari.
Audio System — Dua Layer Musik
WebStory HHC punya dua sistem audio yang independen dan bisa berjalan bersamaan:
Background Music per Slide
Setiap slide bisa punya audio background sendiri via property music. Audio ini loop, volume 0.45 (tidak terlalu keras), dan muted by default (browser policy).
Tombol background music muncul otomatis di header hanya saat ada slide yang punya background music — tidak mengganggu UX di slide yang tidak ada musiknya.
Status muted disimpan di state SWebStorybyHHC.musicMuted — jadi kalau user mute di slide 2, status tersebut dipertahankan di semua slide berikutnya tanpa perlu mute lagi.
Full Music Player
Music player adalah sistem audio yang lebih complex dengan state management sendiri di SWebStorybyHHC.mp:
mp.audio— instance Audio object yang aktifmp.playing— boolean status playbackmp.curTrack— index track yang sedang diputarmp.tracks— array semua trackmp.speed— playback speed saat ini
Saat slide music player aktif, lagu otomatis mulai diputar. Saat user pindah ke slide lain (bukan music player), audio otomatis stop. Ini mencegah situasi membingungkan di mana musik masih terdengar tapi player tidak visible.
muted: true by default. User harus secara aktif menekan tombol unmute — ini bukan bug, ini compliance dengan browser policy yang melindungi user dari konten audio yang tidak diinginkan.
End Screen — Closing yang Berkesan
End screen adalah hal yang sering dilupakan oleh developer story lainnya. WebStory HHC justru menjadikannya sebagai momen spesial — sebuah layar penutup yang kontekstual dan actionable.
End screen secara otomatis tahu apakah ada story berikutnya atau tidak. Kalau ada, tombol "Story Berikutnya" muncul. Kalau ini story terakhir, teks berubah: "Kamu telah menonton semua story. Terima kasih sudah menyimak!"
Pulsing Orb Animation
.ws-end-orbWebStorybyHHC {
/* Radial gradient circle sebagai background orb */
animation: wsEndPulseWebStorybyHHC 2s ease-in-out infinite;
}
@keyframes wsEndPulseWebStorybyHHC {
0%, 100% {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(0,196,154,.3);
/* Ring shadow tidak ada di awal/akhir */
}
50% {
transform: scale(1.06);
box-shadow: 0 0 0 18px rgba(0,196,154,0);
/* Ring shadow expand dan fade out — ripple effect */
}
}
Efek ripple/pulse ini menggunakan box-shadow yang berubah dari rgba(.3) ke rgba(0) (transparent) sambil radius-nya membesar. Ini menciptakan ilusi "gelombang" yang memancar keluar dari pusat — teknik yang lebih efficient dari menggunakan pseudo-element tambahan.
Story Progress Dots
Di end screen ada indicator dots yang menunjukkan posisi story saat ini di antara semua story yang ada. Dot aktif (story yang baru selesai ditonton) berwarna teal dan sedikit lebih besar. Ini memberikan user pemahaman tentang "saya sudah menonton story ke-N dari total M story".
Manfaat Nyata — Why It Matters
Oke, kita udah bahas teknisnya panjang lebar. Sekarang pertanyaan yang lebih penting: apa dampak nyata WebStory HHC untuk blog kamu?
Meningkatkan Time-on-Site & Engagement
Story format secara natural mendorong user untuk terus maju ke slide berikutnya. Auto-advance timer menciptakan sense of urgency, sementara variasi tipe konten (quote, stats, feature, video) mencegah boredom. User yang engage dengan story lebih mungkin untuk juga membaca artikel terkait.
Visual Storytelling yang Lebih Efektif
Konten kompleks bisa dipecah jadi beberapa slide yang digestible. Stats yang terasa kering di artikel biasa menjadi impactful dengan animated counter. Kutipan yang mungkin terlewat di body text jadi focal point di quote slide.
Mobile-First Experience
Format portrait 9:16 adalah native format mobile. Di era di mana 70%+ traffic blog berasal dari mobile, WebStory HHC memberikan experience yang terasa designed untuk device yang user gunakan — bukan seperti desktop site yang di-scale down.
Monetisasi via Sponsored Story
Dengan Sponsored Story mode, kamu bisa menawarkan format iklan premium kepada partner/pengiklan. Story format adalah salah satu ad format dengan engagement rate tertinggi — dan WebStory HHC sudah built-in support untuk ini lengkap dengan disclosure badge otomatis.
SEO Indirect Benefits
Blog feed story yang pull artikel terbaru memberikan "entry point" tambahan untuk konten lama — meningkatkan internal link flow dan memberikan user discovery path yang lebih kaya dari sekadar chronological post list.
WebStory by HHC bukan plugin yang kamu install lalu lupa. Ini adalah investment dalam pengalaman user — dan pengalaman yang baik selalu berbicara sendiri lewat engagement dan trust yang tumbuh.
Han Haoyu — hanhaoyu.com
FAQ — Pertanyaan yang Sering Ditanyain
Apakah WebStory HHC gratis?
WebStory by Han Haoyu tersedia secara gratis untuk digunakan (versi obfuscate). Kunjungi hanhaoyu.com untuk mendapatkan kode terbaru dan dokumentasi lengkap.
Apakah bisa dipakai di platform selain Blogger?
Ya! WebStory HHC adalah pure HTML/CSS/JavaScript tanpa framework — bisa diintegrasikan ke platform web apapun: WordPress, Ghost, custom HTML, dsb. Fitur blog feed otomatis memang dioptimalkan untuk Blogger JSON API, tapi fitur lainnya (static story, music, sponsored) bisa dipakai di platform manapun.
Berapa banyak story dan slide yang bisa dibuat?
Tidak ada limit yang di-hardcode dalam kode. Secara teoritis kamu bisa membuat jumlah story dan slide sebanyak yang kamu mau. Namun secara praktis, lebih dari 10 story circles akan membuat UI terasa penuh, dan lebih dari 15 slide per story mulai menurunkan completion rate.
Bagaimana performa di device lama/lambat?
WebStory HHC dibangun dengan performance sebagai prioritas. Animasi berbasis CSS transforms (bukan JS DOM manipulation), gambar menggunakan lazy loading, dan video tidak di-preload sampai dibutuhkan. Di device modern performanya sangat smooth. Di device lama, animasi mungkin sedikit less smooth tapi functionality tetap berjalan normal.
Apakah support dark mode?
WebStory HHC secara native adalah dark-themed UI — jadi secara default sudah terlihat great di dark mode. Color system berbasis CSS variables memudahkan customisasi kalau kamu ingin mengubah palette untuk light mode.
Closing — Siap Leveling Up?
WebStory by Han Haoyu bukan sekadar widget. Ini adalah manifestasi dari sebuah filosofi: bahwa konten web Indonesia deserves better. Better UX, better performance, better design. Dan tidak ada alasan untuk nggak bisa mencapai itu — bahkan di platform sesederhana Blogger.
Han Haoyu membuktikan bahwa dengan obsesi terhadap detail, pemahaman mendalam tentang web standards, dan komitmen untuk tidak kompromi dengan kualitas — sesuatu yang truly remarkable bisa diciptakan. WebStory HHC adalah buktinya.
🚀 Ready to try? Coba live demo langsung di hanhaoyu.com — lihat sendiri bagaimana rasanya membaca konten dalam format story yang benar-benar didesain dengan penuh cinta.
Artikel Terkait
Copyright (c):
Han Haoyu — hanhaoyu.com
