Anti-Pattern UX Terburuk dan Cara Memperbaikinya
Anti-pattern UX terburuk yang masih dipakai di production, lengkap dengan perbaikan kode sebelum dan sesudah untuk dark pattern, toggle rusak, dan aksesibilitas.

Minggu lalu saya mencoba mengatur preferensi cookie di situs sebuah maskapai besar. Tombol 'Accept All' berwarna biru terang, susah dilewatkan. Tautan 'Manage Preferences'? Teks abu-abu, font 11px, diselipkan di bawah paragraf legalese. Begitu akhirnya ketemu, saya masuk ke halaman dengan 47 toggle switch yang semuanya default-nya menyala, dan tidak ada tombol 'Reject All' sama sekali. Saya duduk di sana selama satu menit penuh mengklik toggle sebelum menyerah dan akhirnya menghapus cookie secara manual.
Ini bukan kejadian sekali saja. Ini sudah jadi norma. UX yang buruk bukan cuma menyebalkan, tapi memusuhi pengguna. Dan yang paling parah? Sebagian besar anti-pattern ini punya perbaikan yang sangat sederhana, dan waktu implementasinya lebih singkat daripada akrobat dark pattern yang menggantikannya. Saya sudah membangun web app selama lebih dari satu dekade, dan saya masih heran kenapa kita terus merilis hal seperti ini. Jadi mari kita bahas pelaku terburuknya dan cara memberantasnya.
Dark Pattern yang Memperlakukan Pengguna seperti Mangsa
Dark pattern bukan kecelakaan. Ada orang yang duduk di rapat, melihat metrik konversi, lalu memutuskan bahwa menipu pengguna adalah strategi bisnis yang bisa diterima. Itulah yang membuat mereka begitu menyebalkan: mereka disengaja.
Confirmshaming: Rasa Bersalah sebagai Elemen UI
Pasti pernah lihat. Sebuah modal muncul meminta Anda berlangganan newsletter. Tombol setuju bertuliskan 'Ya, saya mau hemat!' Tombol tolak bertuliskan 'Tidak, terima kasih, saya lebih suka bayar harga penuh.' Ini namanya confirmshaming, dan ada di mana-mana: situs e-commerce, alur onboarding SaaS, bahkan beberapa developer tool. Cara ini memang berhasil pada segelintir pengguna, tapi membuat sisanya kesal.
Perbaikannya sangat sederhana, sampai memalukan: gunakan bahasa netral untuk kedua opsi.
<!-- BEFORE: Manipulative confirmshaming -->
<div class="modal">
<p>Join 50,000 smart developers!</p>
<button class="btn-primary">Yes, sign me up!</button>
<button class="btn-link text-sm">
No thanks, I don't care about my career
</button>
</div>
<!-- AFTER: Respectful, neutral options -->
<div class="modal">
<p>Get weekly frontend tips — no spam, unsubscribe anytime.</p>
<button class="btn-primary">Subscribe</button>
<button class="btn-secondary">No thanks</button>
</div>
Perhatikan juga bahwa versi sesudahnya menghapus bukti sosial yang dilebih-lebihkan dan menambahkan janji yang jelas soal spam. Rasa hormat membangun kepercayaan lebih baik daripada manipulasi. Konversi jangka panjang Anda akan berterima kasih.
Roach Motel: Daftar dengan Satu Klik, Berhenti dengan Tujuh Langkah
Mendaftar butuh 30 detik. Membatalkan mengharuskan Anda menavigasi ke Settings > Account > Subscription > Manage Plan > Cancel Plan > Tell Us Why > Are You Sure > Talk to Retention > Actually Cancel. Beberapa layanan masih mewajibkan telepon. Di tahun 2026. Untuk membatalkan langganan yang dimulai dengan satu klik.
Saya tidak peduli apa kata metrik retensi Anda. Pengguna yang terjebak bukan pelanggan setia, mereka sandera yang menghasilkan chargeback dan ulasan bintang satu. Buatlah pembatalan semudah pendaftaran.
- Taruh opsi batalkan di Account Settings, tempat orang memang mengharapkannya
- Maksimal dua langkah: 'Anda yakin?' lalu 'Selesai, akun Anda sudah dibatalkan'
- Jangan sembunyikan tombol batalkan di balik tautan 'Contact Support'
- Kalau Anda menawarkan diskon retensi, silakan, tapi jangan jadikan itu langkah wajib dalam alurnya
- Kirim email konfirmasi dengan tautan aktivasi ulang, alih-alih membuat pembatalan terasa tidak bisa diubah
Toggle Switch yang Rusak dan Kontrol UI yang Membingungkan
Ini eksperimen seru: buka pengaturan ponsel Anda dan hitung berapa banyak toggle yang tidak langsung bisa Anda tebak statusnya, nyala atau mati. Saya tunggu.
Toggle yang ambigu adalah salah satu kegagalan UI paling umum yang saya temui saat code review. Toggle seharusnya hanya menyampaikan satu hal: status saat ini. Ini menyala atau mati? Sesederhana itu. Tapi developer terus merilis toggle di mana kedua statusnya tampak hampir sama, atau pewarnaannya ambigu, atau toggle justru menampilkan apa yang akan terjadi berikutnya, bukan apa yang sedang terjadi sekarang.
/* BEFORE: Both states look nearly identical */
.toggle {
width: 48px;
height: 24px;
background: #d1d5db;
border-radius: 12px;
cursor: pointer;
}
.toggle.active {
background: #9ca3af; /* barely different from inactive */
}
/* AFTER: Unmistakable state difference + accessible */
.toggle {
width: 48px;
height: 24px;
background: #d1d5db;
border-radius: 12px;
cursor: pointer;
position: relative;
}
.toggle[aria-checked="true"] {
background: #2563eb; /* strong contrast from inactive */
}
.toggle .label {
font-size: 10px;
font-weight: 600;
color: white;
}
.toggle[aria-checked="true"] .label::after { content: "ON"; }
.toggle[aria-checked="false"] .label::after { content: "OFF"; }
Tiga aturan agar toggle tidak membingungkan: warna berbeda untuk setiap status (dengan kontras yang cukup untuk pengguna buta warna), label teks di dalam atau di samping toggle, dan atribut aria-checked yang tepat supaya screen reader bisa mengumumkan statusnya. Kalau hanya mengandalkan warna, Anda gagal di UX sekaligus aksesibilitas dalam satu langkah.
Berhenti Menciptakan Ulang Form Control Bawaan
Saya me-review banyak PR frontend, dan ada satu pola yang bikin saya naik darah: dropdown buatan sendiri yang merusak navigasi keyboard. Seorang developer menghabiskan dua hari membangun menu select yang keren dari nol dengan banyak div dan click handler. Di demo tampilannya bagus. Lalu pengguna mencoba menelusuri form dengan Tab, menekan dropdown buatan itu, dan tidak terjadi apa-apa. Tidak ada dukungan tombol panah. Tidak ada pencarian ketik-untuk-cari. Tidak kompatibel dengan password manager. Rusak di mobile.
Sementara itu, elemen <select> bawaan, atau library yang sudah teruji seperti Radix UI atau Headless UI, menangani semua ini secara gratis. Popover API HTML dan elemen <selectlist> kini didukung browser dengan baik. Gunakan. Pengguna tidak peduli dropdown Anda punya animasi custom. Mereka peduli apakah itu berfungsi.
Anti-Pattern Aksesibilitas yang Menyingkirkan Pengguna Nyata
Aksesibilitas bukan sekadar fitur tambahan. Bukan sesuatu yang bisa ditambahkan di sprint berikutnya. Lebih dari satu miliar orang di dunia hidup dengan disabilitas dalam bentuk tertentu, dan laporan WebAIM Million secara konsisten menemukan bahwa 96%+ dari satu juta situs teratas memiliki kegagalan WCAG yang bisa dideteksi. Ini bukan kasus pinggiran yang sulit ditemui. Ini tombol yang rusak, label yang hilang, dan gambar tanpa alt text.
Ini yang paling sering saya lihat:
- Gambar tanpa alt text: screen reader cuma bilang 'image' lalu lewat begitu saja
- Rasio kontras di bawah 4,5:1: teks jadi tidak terbaca bagi pengguna dengan low vision
- Tidak ada navigasi keyboard: kalau aplikasi tidak bisa ditelusuri dengan Tab, pengguna keyboard dan switch access terkunci di luar
- Focus trap di modal: pengguna membuka dialog dan tidak bisa keluar tanpa mouse
- Label form yang hilang: screen reader tidak tahu untuk apa sebuah input field
- Video autoplay tanpa tombol pause: membingungkan bagi pengguna dengan gangguan vestibular
Perbaikan tercepat adalah menambahkan pengecekan aksesibilitas otomatis di pipeline CI Anda. Tidak akan menangkap semuanya, karena tool otomatis hanya menemukan sekitar 30-40% masalah, tapi bisa menangkap hal-hal yang jelas sebelum rilis.
// BEFORE: No accessibility testing at all
test('homepage loads', async ({ page }) => {
await page.goto('/');
await expect(page.locator('h1')).toBeVisible();
});
// AFTER: Accessibility violations fail the build
import AxeBuilder from '@axe-core/playwright';
test('homepage loads and is accessible', async ({ page }) => {
await page.goto('/');
await expect(page.locator('h1')).toBeVisible();
const a11yResults = await new AxeBuilder({ page })
.withTags(['wcag2a', 'wcag2aa'])
.analyze();
expect(a11yResults.violations).toEqual([]);
});
Setup-nya cuma lima menit. Berjalan di setiap PR. Otomatis menangkap alt text yang hilang, role ARIA yang rusak, kontras yang kurang, dan puluhan kegagalan lainnya. Tidak ada alasan untuk tidak melakukannya.
Cognitive Overload: Halaman Pengaturan dari Neraka
Working memory manusia hanya menampung sekitar empat sampai tujuh item sekaligus. Ini bukan saran, melainkan batas kognitif yang nyata. Saat antarmuka Anda menumpuk 200 opsi di satu halaman tanpa hierarki, Anda bukan memberi pengguna kendali. Anda memberi mereka kelumpuhan karena terlalu banyak pilihan.
Saya pernah menghitung pengaturan di sebuah tool manajemen proyek yang kami pakai di kantor. 347 opsi. Satu halaman. Tanpa pencarian. Pengelompokan hanya berdasarkan kategori samar seperti 'General' dan 'Advanced'. Separuh tim tidak pernah mengubah satu pengaturan pun karena halamannya begitu membebani sehingga mereka langsung menutupnya.
Perbaikannya adalah progressive disclosure. Tampilkan lima pengaturan yang benar-benar sering diubah orang. Taruh sisanya di balik bagian yang bisa dibuka dan diberi label jelas. Tambahkan kolom pencarian. Dan demi apa pun, sediakan default yang masuk akal supaya kebanyakan pengguna tidak perlu membuka halaman pengaturan sama sekali.
Kalau halaman pengaturan Anda butuh dokumentasinya sendiri, berarti halaman pengaturan Anda itulah masalahnya.
Notification Overload Membuat Pengguna Mengabaikan Semuanya
Saat setiap event memicu notifikasi, seperti rekan satu tim bergabung ke channel, seseorang bereaksi dengan emoji, deploy selesai, atau acara kalender dimulai 30 menit lagi, pengguna belajar mengabaikan semuanya. Sistem notifikasi Anda berubah jadi white noise. Notifikasi kritis yang benar-benar penting? Terkubur di bawah 47 notifikasi belum dibaca.
Jawabannya adalah default yang konservatif. Pengguna baru sebaiknya hanya menerima notifikasi kritis. Kumpulkan hal-hal yang tidak mendesak menjadi digest harian. Dan selalu, selalu, biarkan pengguna membisukan atau menyesuaikan langsung dari notifikasinya, bukan dari halaman preferensi yang tersembunyi tiga klik jauhnya.
UI Lambat Adalah UI yang Rusak: Performa sebagai Masalah UX
Tombol yang butuh dua detik untuk merespons bukan lambat. Itu rusak. Pengguna tidak berpikir 'oh, server sedang memproses permintaan saya.' Mereka berpikir 'klik saya tadi terdaftar atau tidak?' lalu mereka klik lagi. Sekarang Anda punya submit ganda, state yang membingungkan, dan pengguna yang tidak lagi percaya pada aplikasi Anda.
Apa pun di atas 100ms terasa lag. Apa pun di atas satu detik memutus alur pikiran pengguna. Tapi kita terus merilis bundle JavaScript berukuran megabyte, script pihak ketiga yang memblokir render, dan layout shift yang membuat orang mengklik elemen yang salah. Perbaikannya tidak rumit, hanya perlu peduli.
// BEFORE: User clicks, waits 2 seconds, nothing happens
async function handleLike(postId: string) {
const result = await fetch(`/api/posts/${postId}/like`, {
method: 'POST',
});
if (result.ok) {
setLikeCount(prev => prev + 1); // UI updates after network round-trip
}
}
// AFTER: Optimistic update — UI responds instantly
function handleLike(postId: string) {
// Update UI immediately
setLikeCount(prev => prev + 1);
// Sync with server in background
startTransition(async () => {
const result = await fetch(`/api/posts/${postId}/like`, {
method: 'POST',
});
if (!result.ok) {
// Rollback only on failure
setLikeCount(prev => prev - 1);
toast.error('Something went wrong. Try again.');
}
});
}
Optimistic update, skeleton screen sebagai pengganti spinner, JavaScript non-kritis yang di-lazy-load, dan memantau Core Web Vitals sebagai metrik nyata, bukan sekadar pemikiran belakangan. Ini bukan teknik lanjutan. Ini ekspektasi dasar.
Anti-Pattern UX Mobile yang Enggan Mati
Mobile punya kategori dosanya sendiri, sebagian besar karena developer terus menguji di iPhone baru lalu menganggap semuanya beres.
Touch Target yang Butuh Presisi Bedah
Panduan Apple menyebut touch target minimal 44x44 CSS pixel. WCAG 2.2 sepakat. Tapi saya masih sering melihat tombol tutup 20 pixel di modal, tautan kecil yang saling berdesakan di footer, dan tombol ikon yang hampir mustahil diklik di ponsel. Lebih parah lagi bagi pengguna dengan gangguan motorik.
/* BEFORE: Tiny, frustrating touch targets */
.close-btn {
width: 20px;
height: 20px;
font-size: 12px;
}
.footer-links a {
padding: 2px 4px;
font-size: 11px;
}
/* AFTER: Actually tappable elements */
.close-btn {
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
}
.footer-links a {
padding: 12px 8px;
font-size: 14px;
/* spacing between adjacent targets */
margin: 4px 0;
}
Interstitial Layar Penuh yang Menghalangi Konten
Anda mengetuk hasil pencarian. Halaman mulai terbuka. Sebelum Anda bisa membaca satu kata pun, modal layar penuh meminta alamat email Anda. Anda bahkan belum melihat kontennya. Kenapa Anda mau berlangganan?
Google sudah menurunkan peringkat interstitial yang mengganggu di hasil pencarian sejak 2017. Pola ini tetap bertahan karena seseorang di suatu tempat menatap dashboard yang menunjukkan tingkat pengumpulan email 2% lalu menganggapnya kemenangan, sambil mengabaikan bounce rate 40% yang ditimbulkannya. Gunakan banner inline atau bottom sheet. Tunggu sampai pengguna benar-benar berinteraksi dengan konten Anda sebelum meminta apa pun. Pembaca yang sudah menyelesaikan tiga artikel akan berlangganan dengan sukarela. Pembaca yang sudah diganggu tiga kali akan pergi dan tidak akan kembali.
Membangun Budaya Kualitas UX (Bukan Sekadar Memperbaiki Bug Satu per Satu)
Memperbaiki anti-pattern satu per satu itu perlu, tapi belum cukup. Kalau prosesnya terus menghasilkan anti-pattern, Anda butuh proses yang lebih baik. Ini yang benar-benar berhasil:
- Tambahkan axe-core ke pipeline CI Anda: pengecekan a11y otomatis di setiap PR
- Jadikan review UX bagian dari code review, bukan proses terpisah yang hanya untuk desainer
- Uji dengan 5 pengguna nyata sebelum merilis fitur besar. 5 pengguna bisa menemukan sekitar 85% masalah usability
- Lacak tingkat penyelesaian tugas dan tingkat error, bukan hanya page view dan time-on-site
- Gunakan design system dengan komponen aksesibel yang sudah jadi, supaya tiap developer tidak menyelesaikan masalah interaksi yang sama dari nol
- Pakai produk Anda sendiri secara intens. Saat developer yang membangun halaman pengaturan harus menggunakannya setiap hari, halaman itu akan cepat diperbaiki
Perbaikan UX terbaik yang pernah saya buat dimulai ketika saya mencoba memakai alur checkout kami sendiri di ponsel dan mengetik pesan kemarahan ke channel produk jam 11 malam.
Setiap anti-pattern di artikel ini punya perbaikan yang lurus-lurus saja. Tidak ada yang butuh teknologi mutakhir atau redesign besar. Yang dibutuhkan adalah peduli. Mulailah dengan satu perbaikan hari ini. Jalankan satu audit aksesibilitas minggu ini. Uji dengan satu pengguna nyata bulan ini. UX yang baik bukan soal gestur besar, tapi konsisten memilih menghormati pengguna di atas metrik jangka pendek. Jarak antara software yang sekadar ditoleransi orang dan software yang mereka cintai lebih kecil dari yang Anda kira. Hanya seribu keputusan kecil, yang dibuat dengan baik.


