Skip to content

Aksen Nav Berpindah Sendiri, Ternyata Salah Modulo

Adityo Guni Waluyo

Warna entri AI di navbar saya bergeser begitu urutan menu berubah. Pelajaran soal penugasan warna pakai modulo index dan fix berbasis identitas data.

Ringkasan

Warna entri "Tanya AI" di navbar bergeser ternyata karena aksen dihitung pakai modulo index array, bukan bug tema. Perbaikannya mempin warna ke identitas href, plus menambah pill state idle supaya entri khusus beda bentuk sekaligus warna sesuai WCAG. Pelajarannya: identitas visual sebaiknya terikat data, bukan urutan render.

Sore itu saya buka pratinjau staging, dan entri "Tanya AI" di navbar kedapatan warna hijau. Padahal sepanjang minggu dia biru. Saya refresh, cek tab lain, bahkan sempat curiga ada bug di CSS tema. Setelah menelusuri commit, ternyata bukan bug acak. Warna entri nav ditugaskan lewat modulo index array, jadi begitu urutan atau jumlah item berubah, aksen bergeser mengikuti posisi.

Dugaan pertama saya memang ke arah tema. Nyatanya masalahnya ada di baris ini di Navbar.tsx:

color: NAV_COLORS[i % NAV_COLORS.length]

Polanya kelihatan elegan. Array warna diputar pakai modulo supaya tidak pernah melewati batas array. Tapi ada konsekuensi halus yang baru terasa begitu nav ditambah item: identitas visual terikat ke posisi render, bukan ke identitas data. React docs menulis soal pola serupa di konteks lain, bahwa index sebagai identitas sering memunculkan bug yang samar dan membingungkan [3]. Prinsipnya sama untuk styling yang dihitung dari index.

Modulo Enak Saat Nulis, Mahal Saat Merawat

Dengan modulo, entri "AI" di posisi ketiga dapat satu warna. Tambah satu menu di atasnya, dia turun ke posisi keempat dan warnanya bertukar dengan item lain. Dari sisi kode tidak ada yang error. Dari sisi pengguna yang sudah mengenal "Tanya AI" sebagai entri beraksen biru, navigasi tiba-tiba terasa berbeda tanpa alasan yang kelihatan.

Perbaikannya satu kondisi. Karena nav ini punya item khusus dengan route sendiri, warnanya saya pin ke identitas href, bukan ke urutan:

const AI_COLOR = {
  base: "hover:text-primary",
  glow: "rgba(31,111,235,0.20)",
  active: "text-primary",
} as const;

color: link.href === "/ai" ? AI_COLOR : NAV_COLORS[i % NAV_COLORS.length]

Sekarang entri "AI" mempertahankan aksennya di posisi mana pun. Menariknya, commit pertama masih menulis hex hardcoded #1f6feb untuk hover dan active. Enam menit kemudian commit lanjutan menggantinya dengan token tema primary, sekaligus menambah field bernama idle di setiap objek warna. Hardcode hex ternyata umur pendek begitu state tambahan masuk dan butuh konsisten dengan tema.

State Idle Dapat Pill, Warna Saja Tidak Cukup

Field idle itu isinya kelas pill untuk kondisi tidak aktif: bg-primary/10 dipadu text-primary, meniru gaya toggle locale yang aktif. Angka setelah garis miring itu color opacity modifier dari Tailwind untuk mengontrol opasitas warna latar [2], dan pola dasarnya sama dengan variant hover yang hanya bekerja pada state tertentu tanpa efek default [4]. Tiap entri kini membawa empat state dalam satu objek: base, idle, hover, dan active. Objek warna lain juga mendapat field idle, tapi isinya string kosong, jadi hanya entri AI yang tampil sebagai pill ketika tidak aktif. Sisanya tetap polos seperti sebelumnya.

Pill idle bukan sekadar hiasan. WCAG 2.1 pada kriteria 1.4.1 menyebut warna tidak boleh menjadi satu-satunya cara visual menyampaikan informasi [1]. Sebelumnya entri "AI" cuma beda hue di kondisi idle, sama seperti item lain. Setelah ada pill, dia beda bentuk juga. Dua kanal sekaligus, hue dan bentuk, jadi pengguna yang kesulitan membedakan warna tetap bisa mengenali entri ini.

Ada alasan lain yang lebih praktis: WAI menekankan bahwa posisi visual elemen yang konsisten antar halaman memudahkan orang menemukan kembali sebuah mekanisme [5]. Entri khusus seperti asisten AI bekerja mirip. Pengguna yang sudah tahu letaknya akan kecewa kalau entri itu berpindah atau bergaya sewaktu-waktu. Konsistensi visual menopang konsistensi posisi.

Pengalaman ini meninggalkan satu opini yang sekarang saya pegang: identitas visual sebaiknya terikat identitas data, bukan urutan render. Modulo memang enak saat menulis, satu baris selesai. Tapi mahal saat merawat, karena setiap perubahan urutan membayar biayanya di tempat lain. Anchor paling stabil untuk gaya adalah sesuatu yang tidak berubah, misalnya href, id, atau slug, bukan posisi sementara di array.

Sumber

Artikel terkait