Pelajari sistem sederhana untuk konsistenkan loading, error, dan empty state di web dan mobile, agar UI yang dihasilkan AI tetap koheren dan butuh lebih sedikit poles akhir.

Loading, error, dan empty state adalah layar (atau blok UI kecil) yang dilihat orang saat aplikasi menunggu, sesuatu gagal, atau memang tidak ada yang ditampilkan. Ini normal: jaringan lambat, izin ditolak, dan akun baru mulai tanpa data.
Kondisinya cepat berantakan karena biasanya ditambahkan terlambat dan cepat. Tim membangun jalur bahagia dulu, lalu menambal dengan spinner, pesan merah, dan placeholder “tidak ada item” di mana saja UI rusak. Lakukan itu di puluhan layar dan Anda akan punya tumpukan solusi satu-per-satu.
Iterasi cepat memperparahnya. Ketika UI diproduksi dengan cepat (termasuk UI yang dihasilkan AI), tata letak utama bisa muncul dalam hitungan menit, tetapi state ini mudah terlewat. Setiap layar baru berakhir dengan gaya spinner berbeda, frasa berbeda (“Try again” vs “Retry”), dan penempatan tombol berbeda. Kecepatan yang Anda dapat di awal berubah menjadi pekerjaan poles di akhir.
State yang tidak seragam membingungkan pengguna dan memakan waktu tim. Orang tidak bisa membedakan apakah daftar kosong berarti “tidak ada hasil,” “belum dimuat,” atau “Anda tidak punya akses.” QA harus mengetes banyak variasi kecil, dan bug lolos karena perilaku berbeda antara web dan mobile.
“Berantakan” sering terlihat seperti ini:
Tujuannya sederhana: satu pendekatan yang dibagi di web dan mobile. Jika tim Anda menghasilkan fitur cepat (misalnya menggunakan platform seperti Koder.ai), memiliki pola state bersama menjadi lebih penting karena setiap layar baru sudah koheren sejak awal.
Sebagian besar aplikasi mengulang titik-titik tekanan yang sama: daftar, halaman detail, formulir, dashboard. Di sinilah spinner, banner, dan pesan “kosong” bertambah banyak.
Mulailah dengan menamai dan menstandarisasi lima tipe state:
Dua kasus khusus perlu aturan sendiri karena perilakunya berbeda:
Di seluruh layar dan platform, jaga struktur konsisten: tempat state muncul, gaya ikon, nada, dan aksi default (Retry, Refresh, Clear filters, Create). Yang boleh berbeda adalah konteks: nama layar dan kalimat yang memakai kata pengguna.
Contoh: jika Anda menghasilkan daftar web dan daftar mobile untuk “Projects,” keduanya harus berbagi pola zero-results yang sama. Label aksi masih bisa sesuai platform (“Clear filters” vs “Reset”).
Jika setiap layar menemukan spinner, kartu error, dan pesan empty sendiri, Anda akan punya lusinan versi sedikit berbeda. Perbaikan tercepat adalah kit state kecil yang bisa dipakai fitur mana pun.
Mulai dengan tiga komponen yang dapat digunakan ulang dan bekerja di mana saja: Loading, Error, dan Empty. Buat mereka membosankan dengan sengaja. Mereka harus mudah dikenali dan tidak bersaing dengan UI utama.
Buat komponen jadi dapat diprediksi dengan mendefinisikan sekumpulan input kecil:
Lalu tetapkan tampilan. Putuskan sekali untuk spacing, tipografi, ukuran ikon, dan gaya tombol, lalu anggap itu sebagai aturan. Ketika ukuran ikon dan tipe tombol tetap sama, pengguna berhenti memperhatikan UI state dan mulai mempercayainya.
Jaga varian terbatas agar kit tidak berubah jadi sistem desain kedua. Tiga ukuran biasanya cukup: kecil (inline), default (section), dan full-page (blocking).
Jika Anda menghasilkan layar di Koder.ai, instruksi sederhana seperti “use the app StateKit for loading/error/empty with default variant” mencegah drift. Ini juga mengurangi pembersihan akhir di React web dan Flutter mobile.
Copy adalah bagian dari sistem, bukan hiasan. Bahkan ketika tata letak konsisten, frasa ad hoc membuat layar terasa berbeda.
Pilih suara bersama: singkat, spesifik, tenang. Katakan apa yang terjadi dengan bahasa biasa, lalu beri tahu pengguna apa yang harus dilakukan selanjutnya. Sebagian besar layar hanya butuh satu judul jelas, satu penjelasan singkat, dan satu aksi yang jelas.
Beberapa pola pesan menutup sebagian besar situasi. Jaga agar singkat supaya muat di layar kecil:
Hindari teks samar seperti “Something went wrong” sendirian. Jika Anda benar-benar tidak tahu penyebabnya, jelaskan apa yang Anda tahu dan apa yang bisa dilakukan pengguna sekarang. “We couldn’t load your projects” lebih baik daripada “Error.”
Tetapkan satu aturan: setiap error dan empty state menawarkan langkah berikutnya.
Ini lebih penting lagi untuk UI yang dihasilkan AI, di mana layar muncul cepat. Template menjaga copy konsisten sehingga Anda tidak menulis ulang puluhan pesan satu-per-satu saat final polish.
Saat layar state menyarankan aksi berbeda dari halaman ke halaman, pengguna ragu. Tim lalu mengutak-atik tombol dan copy di akhir. Tentukan aksi yang cocok untuk tiap state, dan jaga penempatan serta label tetap konsisten. Sebagian besar layar sebaiknya punya satu aksi utama. Jika menambahkan kedua, harus mendukung jalur utama, bukan bersaing.
Batasi aksi yang diizinkan:
Tombol membosankan adalah fitur. Mereka membuat UI terasa familiar dan membantu layar yang dihasilkan tetap koheren.
Tampilkan “Retry” hanya ketika retry realistis berhasil (timeout, jaringan fluktuatif, 5xx). Tambahkan debounce singkat agar tap berulang tidak membanjiri request, dan ubah tombol ke status loading saat mencoba ulang.
Setelah kegagalan berulang, tetap gunakan tombol utama yang sama dan perbaiki bantuan sekunder (misalnya tip “Check connection” atau “Try again later”). Hindari memperkenalkan tata letak baru hanya karena sesuatu gagal dua kali.
Untuk detail error, tunjukkan alasan singkat yang bisa ditindaklanjuti pengguna (“Your session expired. Sign in again.”). Sembunyikan detail teknis secara default. Jika perlu, sembunyikan di balik affordance “Details” yang konsisten di semua platform.
Contoh: daftar “Projects” gagal dimuat di mobile. Kedua platform menampilkan aksi utama “Retry” yang sama, menonaktifkannya saat mencoba ulang, dan setelah dua kegagalan menambahkan petunjuk koneksi kecil alih-alih mengubah seluruh tata letak tombol.
Perlakukan konsistensi state seperti perubahan produk kecil, bukan redesign. Lakukan bertahap, dan permudah adopsi.
Mulai dengan snapshot cepat dari apa yang sudah ada. Jangan kejar kesempurnaan. Tangkap variasi umum: spinner vs skeleton, error full-page vs banner, layar “no results” dengan nada berbeda.
Rencana rollout praktis:
Setelah komponen ada, penghemat waktu nyata adalah set aturan singkat yang menghilangkan perdebatan: kapan state memblokir seluruh halaman vs hanya sebuah kartu, dan aksi mana yang harus hadir.
Jaga aturan singkat:
Jika Anda menggunakan generator UI AI seperti Koder.ai, aturan ini cepat terasa manfaatnya. Anda bisa mem-prompt “use the state kit components” dan mendapatkan layar yang cocok dengan sistem di React web dan Flutter mobile dengan lebih sedikit pembersihan.
Pekerjaan poles akhir biasanya terjadi karena penanganan state dibangun sebagai satu-per-satu. Sebuah layar “bekerja,” tapi pengalaman terasa berbeda setiap kali sesuatu butuh waktu, gagal, atau tidak ada data.
Skeleton membantu, tapi meninggalkannya terlalu lama membuat orang berpikir aplikasi beku. Penyebab umum adalah menampilkan skeleton penuh pada panggilan lambat tanpa tanda bahwa sesuatu bergerak.
Batasi waktunya: setelah jeda singkat, beralih ke pesan “Still loading…” yang lebih ringan atau tunjukkan progres saat bisa.
Tim sering menulis pesan baru setiap kali, padahal masalahnya sama. “Something went wrong,” “Unable to fetch,” dan “Network error” mungkin menggambarkan satu kasus, tapi terdengar tidak konsisten dan mempersulit dukungan.
Pilih satu label per tipe error dan pakai ulang di web dan mobile, dengan nada dan tingkat detail yang sama.
Kesalahan klasik lain adalah menampilkan empty state sebelum data selesai dimuat, atau menampilkan “No items” saat masalah sebenarnya request gagal. Pengguna mengambil tindakan yang salah (mis. menambah konten padahal seharusnya mencoba ulang).
Buat urutan keputusan eksplisit: loading dulu, lalu error jika gagal, dan empty hanya saat Anda tahu request berhasil.
Error tanpa aksi pemulihan menciptakan dead end. Sebaliknya sering terjadi: tiga tombol yang saling bersaing.
Jaga singkat:
Perbedaan kecil menumpuk: gaya ikon, padding, bentuk tombol. Inilah juga area di mana UI yang dihasilkan AI bisa menyimpang jika prompt berbeda per layar.
Kunci spacing, set ikon, dan tata letak untuk komponen state agar setiap layar baru mewarisi struktur yang sama.
Jika Anda ingin penanganan state konsisten di web dan mobile, buat aturan “membosankan” itu eksplisit. Sebagian besar pekerjaan poles akhir muncul karena setiap layar menemukan perilaku loading, timeout, dan label sendiri.
Untuk full page load, pilih satu default: skeleton untuk layar berisi konten berat (daftar, kartu, dashboard) dan spinner untuk tunggu singkat ketika tata letak belum jelas.
Tambahkan threshold timeout agar UI tidak tergantung. Jika loading lebih dari sekitar 8–10 detik, beralih ke pesan jelas dan aksi terlihat seperti “Retry.”
Untuk partial load, jangan blank layar. Pertahankan konten yang ada terlihat dan tunjukkan indikator progres kecil di dekat bagian yang sedang diperbarui (mis. bar tipis di header atau spinner inline).
Untuk data cache, lebih memilih “stale but usable.” Tampilkan konten cache segera dan tambahkan indikator halus “Refreshing…” agar orang mengerti data mungkin berubah.
Offline adalah state sendiri. Katakan dengan jelas, dan jelaskan apa yang masih berfungsi. Contoh: “You’re offline. You can view saved projects, but syncing is paused.” Tawarkan satu langkah berikutnya seperti “Try again” atau “Open saved items.”
Jaga ini konsisten di seluruh platform:
Jika Anda menghasilkan UI dengan alat seperti Koder.ai, memasukkan aturan ini ke dalam StateKit bersama membantu menjaga setiap layar baru konsisten secara default.
Bayangkan CRM sederhana dengan layar daftar Contacts dan layar detail Contact. Jika Anda memperlakukan loading, error, dan empty state sebagai satu-per-satu, web dan mobile akan cepat menyimpang. Sistem kecil menjaga semuanya selaras meski UI diproduksi cepat.
First-time empty state (Contacts list): pengguna membuka Contacts dan belum ada. Di web dan mobile, judul tetap sama (“Contacts”), pesan empty menjelaskan kenapa (“No contacts yet”), dan satu langkah berikutnya jelas ditawarkan (“Add your first contact”). Jika perlu setup (mis. menghubungkan inbox atau mengimpor CSV), empty state menunjuk langkah itu secara tepat.
Slow network loading: pengguna membuka halaman detail Contact. Kedua platform menampilkan skeleton tata letak yang dapat diprediksi sesuai struktur halaman akhir (header, field kunci, catatan). Tombol kembali tetap berfungsi, judul halaman terlihat, dan Anda menghindari spinner acak di tempat berbeda.
Server error: request detail gagal. Polanya sama di web dan mobile: headline pendek, satu kalimat, dan aksi utama (“Retry”). Jika retry gagal lagi, tawarkan opsi kedua seperti “Go back to Contacts,” agar pengguna tidak terjebak.
Yang tetap konsisten itu sederhana:
Sebuah rilis bisa terlihat “selesai” sampai seseorang mengalami koneksi lambat, akun baru, atau API fluktuatif. Daftar ini membantu menemukan celah akhir tanpa membuat QA jadi perburuan.
Mulai dengan layar daftar, karena mereka banyak. Pilih tiga daftar umum (hasil pencarian, item tersimpan, aktivitas terbaru) dan pastikan semuanya memakai struktur empty-state yang sama: judul jelas, satu kalimat membantu, dan satu aksi utama.
Pastikan empty state tidak pernah muncul saat data masih dimuat. Jika Anda menampilkan “Nothing here yet” sebentar lalu menggantinya dengan konten, kepercayaan turun cepat.
Periksa indikator loading untuk konsistensi: ukuran, penempatan, dan durasi minimum yang masuk akal supaya tidak berkedip. Jika web menampilkan spinner bar atas tapi mobile menampilkan skeleton layar penuh untuk layar yang sama, terasa seperti dua produk berbeda.
Error harus selalu menjawab “sekarang apa?” Setiap error butuh langkah berikutnya: retry, refresh, ubah filter, sign in lagi, atau hubungi support.
Lakukan pengecekan cepat sebelum menandai build siap:
Jika Anda menggunakan pembuat AI seperti Koder.ai, pemeriksaan ini lebih penting karena layar bisa dibuat cepat, tapi konsistensi tetap bergantung pada kit bersama dan aturan copy.
Konsistensi paling mudah saat jadi bagian pekerjaan sehari-hari, bukan pembersihan satu kali. Setiap layar baru harus memakai pola yang sama tanpa ada yang mengingatkan “cocokkan ini” di akhir.
Jadikan perilaku state bagian dari definition of done. Sebuah layar belum selesai sampai punya loading state, empty state (jika relevan), dan error state dengan aksi jelas.
Tulis aturan ringkas, tapi dokumentasikan. Dokumen singkat dengan beberapa tangkapan layar dan pola copy yang diinginkan biasanya cukup. Perlakukan varian baru sebagai pengecualian. Ketika seseorang mengusulkan desain state baru, tanyakan apakah itu benar-benar kasus baru atau cocok dengan kit.
Jika Anda merombak banyak layar, kurangi risiko dengan langkah terkontrol: perbarui satu alur sekaligus, verifikasi di web dan mobile, lalu lanjutkan. Di Koder.ai, snapshot dan rollback bisa membuat perubahan besar lebih aman, dan planning mode membantu mendefinisikan StateKit bersama sehingga layar yang dihasilkan mengikuti default Anda sejak hari pertama.
Pilih satu area minggu ini di mana masalah state menyebabkan perbaikan akhir (sering search results, onboarding, atau activity feed). Lalu:
Tanda konkret bahwa ini berhasil: lebih sedikit tiket kecil seperti “add retry,” “empty state looks weird,” atau “loading spinner blocks the page.”
Tunjuk satu pemilik untuk standar state (desainer, tech lead, atau keduanya). Mereka tidak perlu menyetujui semuanya, tapi harus menjaga kit supaya tidak perlahan-lahan terpecah menjadi varian baru yang mirip, berperilaku berbeda, dan memakan waktu di kemudian hari.
Mulailah dengan menamai sekumpulan kecil state yang akan dipakai di mana-mana: initial loading, refreshing, empty baseline, zero results, dan error. Tambahkan aturan eksplisit untuk offline dan jaringan lambat supaya keduanya tidak diperlakukan sebagai error acak. Setelah tim sepakat pada nama dan trigger, UI menjadi lebih bisa diprediksi di seluruh layar dan platform.
Buat StateKit kecil dengan tiga bagian yang dapat digunakan ulang: Loading, Error, dan Empty. Pastikan setiap komponen dikendalikan oleh input yang sama (title, pesan singkat, satu aksi utama, dan detail opsional) sehingga setiap layar bisa langsung menggunakannya tanpa membuat UI baru. Buat varian default semudah mungkin agar tim berhenti membuat solusi satu-satu.
Gunakan urutan keputusan sederhana: tampilkan loading sampai request selesai, lalu tampilkan error jika gagal, dan hanya tunjukkan empty setelah respons berhasil namun tanpa data. Ini mencegah bug umum di mana “Tidak ada item” muncul sebentar sebelum konten muncul. Cara ini juga memudahkan QA karena perilaku konsisten di mana-mana.
Pilih satu aksi default per state dan gunakan label serta posisinya secara konsisten di seluruh layar. Error biasanya mendapat “Retry”, empty baseline mendapat “Create” (atau langkah setup berikutnya), dan zero results mendapat “Clear filters”. Saat aksi utama bisa diprediksi, pengguna bergerak lebih cepat dan tim tidak perlu berdebat soal kata pada tombol.
Tulis copy dalam template bersama: judul pendek yang menjelaskan situasi, satu kalimat singkat yang menjelaskannya dengan bahasa biasa, dan satu langkah jelas berikutnya. Pilih pesan spesifik seperti “We couldn’t load your projects” daripada yang samar seperti “Something went wrong.” Jaga nada tetap tenang dan konsisten sehingga web dan mobile terasa seperti satu produk.
Perlakukan offline sebagai state tersendiri, bukan error umum. Tampilkan konten yang di-cache bila ada, katakan “You’re offline” dengan jelas, dan jelaskan apa yang masih bisa dilakukan sekarang. Berikan satu langkah berikutnya seperti “Try again” agar pengguna tidak kebingungan.
Jangan langsung menampilkan error pada koneksi lambat; tunggu sebentar sebelum mengganti UI. Jika loading melewati ambang tertentu, beralihlah ke pesan gaya “Still loading…” dan sediakan aksi terlihat seperti “Retry.” Ini membuat aplikasi terasa responsif meski jaringan lambat.
Gunakan tiga varian ukuran: inline kecil (di dalam card atau section), section default, dan full-page yang memblokir. Definisikan kapan masing-masing boleh digunakan supaya tim tidak berimprovisasi per layar. Menjaga spacing, gaya ikon, dan gaya tombol sama di seluruh varian itulah yang membuat pengalaman terasa konsisten.
Masukkan beberapa aturan: pindahkan fokus ke pesan dan aksi utama saat state muncul, umumkan loading dan error dengan label yang jelas, dan pastikan tombol mudah ditekan. Jangan mengandalkan warna atau animasi saja untuk menyampaikan status. Jika aturan ini bagian dari StateKit, setiap layar baru otomatis mewarisinya.
Lakukan rollout per area produk, mulai dari list dan detail layar yang sering dipakai. Inventarisasi apa yang ada, pilih beberapa penempatan kanonik, lalu ganti state satu-per-satu ketika Anda mengubah layar itu. Jika Anda menghasilkan UI di Koder.ai, tambahkan instruksi tetap agar memakai StateKit secara default supaya layar baru tidak menyimpang.