Enam chapter terakhir membangun satu kebiasaan yang sama: memilih komponen interaktif yang bekerja untuk semua pengunjung, bukan hanya untuk yang memakai mouse. Chapter ini merangkum aturan besar section Interactive Elements dari sudut pandang accessibility. Kita ulas mengapa elemen native menjadi titik awal, bagaimana dialog mengelola fokus, ARIA apa saja yang menemani pola custom, lalu menutupnya dengan checklist audit yang bisa dipakai langsung.

Mulai dari Elemen Native #

Elemen native membawa semantik, keyboard, dan pengumuman pembaca layar sejak lahir. details bisa dibuka dengan klik maupun Enter dan Space, lengkap dengan status dibentangkan yang diumumkan otomatis. Dialog modal mengunci halaman di belakangnya dan menyediakan tombol Escape tanpa satu baris skrip. progress dan meter menyampaikan nilainya sebagai bagian dari accessibility tree. Setiap penggantian elemen native dengan versi custom berarti menanggung ulang biaya-biaya tersebut.

AspekElemen nativePola custom
Semantik dan peranDiberikan browserDitulis lewat ARIA
KeyboardOtomatisDiuji sendiri
Status diumumkanOtomatisPerlu aria-expanded atau aria-pressed
Fokus dan Escape (dialog modal)Diatur showModalDitulis JavaScript sendiri
Biaya aksesibilitasNolIkut setiap perubahan kode

Fokus di Dalam Dialog Modal #

Method showModal() melakukan tiga pekerjaan fokus sekaligus. Saat dialog terbuka, fokus berpindah ke elemen pertama di dalam dialog yang bisa difokuskan — atau ke elemen beratribut autofocus. Selama dialog terbuka, tekanan Tab berputar di dalam dialog saja, sehingga fokus tidak lolos ke halaman di belakang. Saat dialog ditutup, browser mengembalikan fokus ke elemen yang memicunya, sehingga pengguna keyboard melanjutkan dari tempat semula.

Mode non-modal show() tidak memberi pengelolaan fokus apa pun. Bila memakai mode itu, kita yang memindahkan fokus ke dialog saat dibuka dan mengembalikannya saat ditutup.

ARIA untuk Pola Custom #

Pola custom membayar biaya aksesibilitasnya lewat atribut ARIA. aria-expanded pada tombol pemicu mengumumkan status region, aria-controls menautkan tombol dengan id regionnya, dan aria-pressed menyatakan tombol toggle. Atribut hidden melengkapi ketiganya dengan mengeluarkan region dari render sekaligus dari accessibility tree. Ingat kembali batasannya: ARIA hanya mengumumkan, sementara perilakunya tetap lahir dari JavaScript yang kita tulis.

Checklist Audit Komponen Interaktif #

Sebelum komponen interaktif dikatakan siap, jalankan audit singkat berikut. Setiap butir berasal dari materi section ini serta pedoman web.dev dan WAI:

  • Seluruh aksi dapat dijalankan dengan keyboard saja: Tab untuk berpindah, Enter dan Space untuk tombol, Escape untuk dialog modal.
  • Indikator fokus terlihat jelas pada setiap kontrol yang bisa difokuskan.
  • Setiap kontrol memiliki accessible name yang menjelaskan tujuannya, misalnya teks summary atau teks tombol.
  • Status terbuka, tertutup, atau tertekan diumumkan, baik otomatis dari elemen native maupun lewat aria-expanded dan aria-pressed.
  • Konten yang tersembunyi benar-benar keluar dari jalur fokus dan dari pembacaan pembaca layar, melalui atribut hidden.
  • Kontras antara teks dan latarnya memenuhi pedoman WCAG.

Kita wujudkan checklist itu menjadi halaman audit yang bisa dicentang. Skor pada bagian atas halaman naik setiap butir terpenuhi.

<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Audit Komponen Interaktif</title>
  <style>
    body {
      font-family: sans-serif;
      max-width: 480px;
      margin: 24px auto;
      line-height: 1.6;
    }
    li {
      margin-bottom: 8px;
    }
    #status-audit {
      font-weight: bold;
      color: #1a6b54;
    }
  </style>
</head>
<body>
  <h1>Audit Komponen Interaktif</h1>
  <p id="status-audit">0 dari 5 item terpenuhi</p>
  <ul id="daftar-audit">
    <li><label><input type="checkbox"> Komponen bisa dijalankan lewat keyboard</label></li>
    <li><label><input type="checkbox"> Indikator fokus terlihat jelas</label></li>
    <li><label><input type="checkbox"> Setiap kontrol punya nama yang jelas</label></li>
    <li><label><input type="checkbox"> Status dibentangkan atau ditekan diumumkan</label></li>
    <li><label><input type="checkbox"> Kontras teks dan latar memenuhi WCAG</label></li>
  </ul>

  <script>
    const statusAudit = document.querySelector("#status-audit");
    const semuaKotak = document.querySelectorAll("#daftar-audit input");
    const total = semuaKotak.length;

    function perbaruiStatus() {
      let terpenuhi = 0;
      semuaKotak.forEach(function (kotak) {
        if (kotak.checked) {
          terpenuhi = terpenuhi + 1;
        }
      });
      statusAudit.textContent = terpenuhi + " dari " + total + " item terpenuhi";
    }

    semuaKotak.forEach(function (kotak) {
      kotak.addEventListener("click", perbaruiStatus);
    });
  </script>
</body>
</html>

Output yang Dihasilkan:

text
Saat halaman baru dibuka:
  - Teks "0 dari 5 item terpenuhi" berada di atas daftar
Setiap kotak centang ditekan, lewat mouse maupun keyboard:
  - Angka pada teks status naik mengikuti jumlah kotak tercentang
Setelah kelima kotak tercentang:
  - Status menjadi "5 dari 5 item terpenuhi"

Mari kita bedah isi halaman itu:

  1. <label><input type="checkbox"> ...</label>: label membungkus kotaknya, sehingga teks butir menjadi accessible name kotak tersebut — contoh nyata butir ketiga checklist.
  2. querySelectorAll("#daftar-audit input"): mengambil seluruh kotak centang sekaligus ke dalam satu NodeList.
  3. Function perbaruiStatus: menelusuri kotak dengan forEach, menambah hitungan untuk setiap kotak dengan properti checked bernilai true, lalu menulis hasilnya ke teks status.
  4. Listener click pada setiap kotak: memanggil perbaruiStatus; penekanan Space pada kotak centang juga memicu event click yang sama.

Dengan checklist ini, rangkaian section Interactive Elements tuntas; pola-pola di atas akan terus terpakai pada section-section berikutnya. Setelah ini kita masuk ke section Embedded Content, yang membahas cara menampilkan dokumen dan aplikasi lain di dalam halaman, dimulai dari elemen iframe.

Referensi resmi untuk pendalaman:

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

audit-interaksi.html

Unduh berkas
html
<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Audit Komponen Interaktif</title>
  <style>
    body {
      font-family: sans-serif;
      max-width: 480px;
      margin: 24px auto;
      line-height: 1.6;
    }
    li {
      margin-bottom: 8px;
    }
    #status-audit {
      font-weight: bold;
      color: #1a6b54;
    }
  </style>
</head>
<body>
  <h1>Audit Komponen Interaktif</h1>
  <p id="status-audit">0 dari 5 item terpenuhi</p>
  <ul id="daftar-audit">
    <li><label><input type="checkbox"> Komponen bisa dijalankan lewat keyboard</label></li>
    <li><label><input type="checkbox"> Indikator fokus terlihat jelas</label></li>
    <li><label><input type="checkbox"> Setiap kontrol punya nama yang jelas</label></li>
    <li><label><input type="checkbox"> Status dibentangkan atau ditekan diumumkan</label></li>
    <li><label><input type="checkbox"> Kontras teks dan latar memenuhi WCAG</label></li>
  </ul>

  <script>
    const statusAudit = document.querySelector("#status-audit");
    const semuaKotak = document.querySelectorAll("#daftar-audit input");
    const total = semuaKotak.length;

    function perbaruiStatus() {
      let terpenuhi = 0;
      semuaKotak.forEach(function (kotak) {
        if (kotak.checked) {
          terpenuhi = terpenuhi + 1;
        }
      });
      statusAudit.textContent = terpenuhi + " dari " + total + " item terpenuhi";
    }

    semuaKotak.forEach(function (kotak) {
      kotak.addEventListener("click", perbaruiStatus);
    });
  </script>
</body>
</html>