Skip to content
Konsultasi

Chat Kiri, Hasil Kanan: Satu Overlay Dipecah Dua

Adityo Guni Waluyo

Chat dan daftar sumber rebutan ruang di satu overlay. Solusinya dua panel z-index beda plus visibilitas popup yang dihitung saat render.

Jawaban AI lagi streaming, daftar artikel sumber keluar di popup. Saya geser popupnya ke kiri biar baca, dan chat sidebar ketutup total. Geser balik ke kanan, daftar sumber yang tadi kelihatan jadi hilang. Dua elemen ini berebut satu ruang overlay yang sama, dan nggak ada posisi yang bikin keduanya terbaca sekaligus.

Awalnya saya pikir masalahnya di z-index. Kasih nilai lebih tinggi ke results popup supaya dia selalu di atas, selesai kan? Tapi itu justru bikin chat nggak bisa diakses sama sekali kalau popup terbuka. Bukan solusi, cuma ganti masalah lama dengan yang baru.

Satu boolean, dua masalah

Rencana awal: tambahin state popupVisible, bikin useEffect yang sinkronin nilai itu ke jawaban AI. State baru, effect baru, logic baru. Tiga hal yang harus dijaga tetep sinkron.

Tapi saya mikir lagi. Visibilitas popup itu sebenernya udah bisa dihitung dari state yang ada. Ada jawaban yang selesai dijawab? Berarti kandidat muncul. Analisis masih jalan? Belum waktunya muncul. ID jawaban sama dengan yang di-dismiss? Berarti user baru aja tutup, jangan munculin lagi. Tiga kondisi itu cukup buat nentuin popup keliatan atau nggak, dan semuanya bisa dihitung langsung saat render, nggak perlu state baru sama sekali. Prinsipnya persis yang didokumentasikan React: kalau sesuatu bisa dihitung saat rendering, kamu nggak butuh state atau Effect buat mengupdatenya [1].

Lebih banyak state sama aja dengan lebih banyak tempat bug ngumpet. Satu boolean popupVisible yang salah sinkron aja udah cukup bikin popup nongol di waktu yang salah, atau nggak ilang pas harusnya ilang. Saya pernah kejadian semacam itu di fitur lain: dua sumber kebenaran buat satu hal, lama-lama nggak jelas mana yang bener. Sejak itu saya curiga sama state baru, nunggu sampai kebuktiin nggak bisa dihitung dari yang udah ada.

Dua panel, dua z-index

Jadi satu overlay dipecah jadi dua permukaan yang berdiri sendiri.

Sidebar chat nempel di kiri, full-height, geser masuk dari kiri. Z-index 40. Toggle-nya pakai ikon Sparkles, kirim pesan pakai tombol ArrowUp di bawah input, dan kalau thread masih kosong muncul greeting chips. Semua logika thread tetap, nggak ada yang dirombak. Cuma posisi dan cara masuknya aja yang beda dari sebelumnya.

Results popup nempel di kanan, geser masuk dari kanan. Z-index lebih tinggi, 50. Di CSS, properti z-index nentuin urutan tumpuk elemen yang diposisikan, dan elemen dengan nilai lebih besar nutupin yang lebih kecil [3]. Jadi kalau keduanya kebuka bareng di mobile, popup menutupi chat. Itu disengaja, karena baca sumber jawaban lebih urgent daripada liat chat history pas jawaban baru muncul. Ada badge “Dipakai jawaban” plus nomor sitasi, ada tombol X buat dismiss. Baris-baris artikel di dalamnya distyle ulang jadi mirip kartu blog: ada tanggal terformat, ada tile ikon buat nunjukin stack teknologi.

Di layar lebar, popup nggak nutupin chat sama sekali: dia nempel di kanan dengan lebar sendiri, chat tetep kebaca di kiri. Rebutan ruang cuma terjadi di layar kecil, dan di situ z-index yang mutusin. Geser masuknya keduanya pakai animasi 200 milidetik. Dan karena media query prefers-reduced-motion itu mendeteksi apakah user minta sistem operasinya minimalin animasi dan gerakan, saya tambahin kelas animasi slide kiri dan kanan ke daftar selector yang dapet animation: none di media query itu [2]. User yang minta nggak ada gerakan dapet pengalaman statis yang bersih.

Visibilitas popup tetap dihitung saat render: popup muncul hanya bila ada jawaban, tidak lagi menganalisis, dan belum di-dismiss untuk jawaban itu. Dismiss dipasang ke id jawaban spesifik, jadi tombol X cuma nyembunyikan popup untuk jawaban itu aja. Jawaban berikutnya selesai? Popup muncul lagi otomatis.

State yang bisa dihitung nggak perlu disimpan. Z-index menentukan siapa nutupin siapa. Dan dua panel yang masing-masing punya arah gerak sendiri jauh lebih gampang diurus daripada satu overlay yang jadi tumpuk-tumpukan. Kalau mau tahu gimana thread percakapan di dalamnya dibangun, udah saya tulis terpisah soal dialog cari yang jadi thread percakapan.

Sumber

Artikel terkait