Dasar Aksesibilitas di Komponen Vue

Setiap kali saya membangun komponen UI dengan Vue — entah itu untuk dashboard internal Filament, atau bagian frontend aplikasi klinik yang saya tangani sehari-hari — ada satu hal yang gampang sekali terlewat: aksesibilitas. Bukan karena kita tidak peduli, tapi karena komponen biasanya "kelihatan" berfungsi di browser kita sendiri, dengan mouse dan mata normal. Masalahnya baru muncul ketika dipakai orang lain: staf yang mengandalkan keyboard karena mouse rusak, pengguna dengan low vision, atau sekadar orang yang membuka aplikasi di layar dengan kontras rendah. Di dunia sistem informasi kesehatan, di mana aplikasi dipakai petugas dengan latar belakang teknis yang sangat beragam, hal ini menurut saya bukan lagi "nice to have".

Kabar baiknya, aksesibilitas di komponen Vue tidak butuh audit besar-besaran untuk mulai. Ada beberapa praktik dasar yang kalau konsisten diterapkan, sudah menutup sebagian besar celah paling umum.

Label yang benar-benar terhubung ke input

Ini yang paling sering saya temui salah di komponen custom: label ada secara visual, tapi tidak terhubung secara teknis ke elemen input-nya. Screen reader tidak bisa "menebak" hubungan itu hanya dari posisi di layar.

Cara paling aman adalah pasangan <label for="..."> dengan id yang sama di input. Sebagai ilustrasi, dalam komponen Vue sederhana:

<template>
  <label :for="inputId">Nama Pasien</label>
  <input :id="inputId" v-model="nama" type="text" />
</template>

Kalau komponen dipakai berkali-kali dalam satu halaman (misalnya form dinamis), pastikan id di-generate unik per instance, bukan di-hardcode. Untuk komponen yang tidak punya label visual sama sekali — ikon tombol misalnya — gunakan atribut aria-label agar tetap terbaca oleh assistive technology.

Kontras warna yang cukup

Ini area yang paling sering korban dari selera desain. Warna abu-abu muda di atas putih terlihat elegan, tapi kalau rasio kontrasnya terlalu rendah, teks itu praktis tidak terbaca bagi sebagian pengguna. Pedoman umum yang saya pakai sebagai acuan: teks biasa idealnya punya rasio kontras minimal sekitar 4.5:1 terhadap latar belakangnya, dan teks besar atau tebal sedikit lebih longgar.

Yang penting di level komponen: jangan cuma andalkan warna untuk menyampaikan status. Kalau ada badge "error" berwarna merah, tambahkan juga ikon atau teks, bukan warna saja — karena pengguna dengan buta warna tertentu bisa saja tidak membedakan merah dari hijau.

Navigasi keyboard yang tidak terjebak

Komponen interaktif seperti modal, dropdown, atau tab custom sering dibangun dengan div ber-@click, tanpa memikirkan bagaimana elemen itu dijangkau lewat tombol Tab. Beberapa hal dasar yang saya selalu cek:

  • Elemen yang bisa diklik harus bisa difokus dengan keyboard — kalau bukan elemen native seperti <button> atau <a>, tambahkan tabindex="0" dan handler untuk event keyboard, bukan cuma click.
  • Urutan fokus harus masuk akal secara logis, mengikuti alur visual, bukan urutan acak akibat position: absolute atau grid yang di-reorder secara visual.
  • Modal atau dialog sebaiknya "menjebak" fokus di dalamnya selama terbuka (focus trap), dan mengembalikan fokus ke elemen pemicu saat ditutup — kalau tidak, pengguna keyboard bisa "hilang arah" di halaman.
  • Tombol Escape sebaiknya konsisten dipakai untuk menutup overlay, sesuai ekspektasi umum pengguna.

Vue sendiri tidak otomatis menyelesaikan ini untuk kita — semua tetap perlu ditulis eksplisit di template dan handler. Yang membantu adalah membiasakan diri memakai elemen HTML native (button, select, label) dulu sebelum membangun ulang perilakunya dari nol dengan div, karena elemen native sudah membawa banyak perilaku aksesibilitas secara bawaan.

Takeaway

Aksesibilitas di komponen Vue bukan proyek besar terpisah, tapi kebiasaan kecil yang ditanam sejak komponen pertama kali ditulis: label yang benar-benar terhubung, kontras yang cukup, dan navigasi keyboard yang jalan tanpa jebakan. Kalau tiga hal ini sudah jadi standar minimal di tim, sebagian besar keluhan aksesibilitas yang paling umum sudah tertutup sebelum sempat jadi masalah di produksi.