Komponen · · 3 menit baca
Komponen UI: BrowserFrame, SystemFlow & Stat — dengan contoh live
Tiga komponen server-first yang dipakai di seluruh situs ini — mockup browser, diagram arsitektur dari tag, dan angka count-up — dirender live di halaman ini, lengkap dengan source code-nya.
AI coverage
Load on 4G
Tiga komponen kecil ini muncul di hampir setiap halaman situs ini: BrowserFrame (bingkai browser untuk mockup), SystemFlow (diagram alur sistem), dan Stat (angka yang menghitung naik saat terlihat). Contoh live-nya dirender langsung di atas ↑ — bukan gambar. Ini source code dan keputusan desain di baliknya.
BrowserFrame — mockup tanpa screenshot
Masalahnya: butuh menampilkan “produk” sebelum screenshot asli tersedia. Solusinya bingkai chrome browser minimal — tiga titik, address bar, lalu slot children untuk isi apa pun:
export const BrowserFrame = ({ url, children }: { url: string; children?: Child }) => (
<div class="card overflow-hidden">
<div class="flex items-center gap-3 border-b border-line bg-surface px-4 py-2.5">
<div class="flex gap-1.5" aria-hidden="true">
<span class="h-2 w-2 rounded-full border border-line bg-base"></span>
<span class="h-2 w-2 rounded-full border border-line bg-base"></span>
<span class="h-2 w-2 rounded-full border border-line bg-base"></span>
</div>
<div class="min-w-0 flex-1 truncate rounded-sm border border-line bg-base px-3 py-1
font-mono text-[10px] tracking-[0.06em] text-muted">{url}</div>
</div>
<div class="bg-base">{children}</div>
</div>
);
Detail yang penting: min-w-0 + truncate di address bar. Tanpa itu, URL panjang memaksa lebar minimum konten melebihi viewport HP — halaman “mengecil” ke kiri (bug nyata yang pernah terjadi di situs ini).
SystemFlow — diagram arsitektur dari tag
Diagram alur (Storefront → Checkout → AI chat → RAG → Ops) tanpa library diagram: hanya deretan tag dengan “beam” animasi di antaranya. Di mobile, beam disembunyikan dan tag dibiarkan wrap:
export const SystemFlow = ({ nodes }: { nodes: string[] }) => (
<div class="flex flex-wrap items-center justify-center gap-2 py-1 md:flex-nowrap md:gap-0"
role="img" aria-label="System flow diagram">
{nodes.map((node, i) => (
<>
{i > 0 && <span class="beam hidden w-10 shrink-0 md:block" aria-hidden="true"></span>}
<span class="tag shrink-0 bg-base">{node}</span>
</>
))}
</div>
);
role="img" + aria-label membuat screen reader membacanya sebagai satu diagram, bukan lima tag acak.
Stat — angka yang menghitung naik
Server merender nilai akhir di atribut data-count (SEO dan pengguna tanpa JS tetap dapat angkanya — teks awal prefix + 0 + suffix diganti CSS/JS hanya saat JS aktif). Vanilla JS di site.js menganimasikannya saat elemen masuk viewport lewat IntersectionObserver:
export const Stat = ({ prefix, count, suffix, label, delay }: StatProps) => (
<div class="text-center" data-reveal style={"--d: " + delay}>
<div class="font-display text-4xl font-semibold tracking-tight md:text-5xl">
<span data-count={count} data-prefix={prefix} data-suffix={suffix}>{prefix}0{suffix}</span>
</div>
<p class="mt-2 font-mono text-[11px] uppercase tracking-[0.18em] text-muted">{label}</p>
</div>
);
Prinsip di balik ketiganya
- Server-first: semua konten ada di HTML awal; JavaScript hanya menambah gerak.
- Nol dependensi: tidak ada library carousel/diagram/count-up — total JS situs tetap di bawah 20KB.
- Mobile ditegakkan dengan kelas, bukan JS:
flex-wrap,hidden md:block,min-w-0— layout tidak pernah bergantung pada perhitungan runtime.
Mau fitur seperti ini dibangun untuk bisnismu?