Belajar Frontend - Accessible & Inclusive Design
Episode 15 of 28

Belajar Frontend - Accessible & Inclusive Design

Mendalami aksesibilitas dari episode 3: peran ARIA dan kapan memakainya, navigasi keyboard & fokus, kontras warna, serta pengujian aksesibilitas otomatis dengan axe dan Playwright — lewat audit menyeluruh TokoKita

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Di episode 3 kita menyentuh dasar aksesibilitas (WCAG/POUR). Episode 15 mendalaminya secara sistematis. Di 2026 aksesibilitas bukan lagi "nice to have": peraturan seperti EU Accessibility Act menjadikannya syarat hukum, dan pengguna dengan disabilitas adalah pengguna nyata yang menguji produk kalian setiap hari.

Pendekatan yang akan kita pakai: built-in semantics first — gunakan elemen HTML yang benar sejak awal (sudah dipelajari di episode 3), tambah ARIA hanya untuk mengisi celah yang benar-benar ada, lalu verifikasi dengan alat otomatis dan pengecekan manual keyboard.

ARIA: Kapan dan Mengapa

ARIA (Accessible Rich Internet Applications) adalah atribut yang menambahkan informasi semantik untuk teknologi bantu. Aturan pertamanya: jangan memakai ARIA bila elemen HTML sudah menyediakan semantiknya.

HTMLContoh yang benar dan yang tidak perlu
<!-- ✅ BENAR: button asli, semantik gratis -->
<button>Beli sekarang</button>
 
<!-- ❌ SALAH: div dijadikan tombol, perlu ARIA + keyboard manual -->
<div role="button" tabindex="0" onclick="buy()">Beli sekarang</div>

Kapan ARIA memang dibutuhkan:

HTMLARIA yang bermanfaat
<!-- Label untuk elemen yang tidak punya label visual -->
<button aria-label="Tutup dialog">×</button>
 
<!-- Status yang berubah tanpa focus -->
<div role="status" aria-live="polite">Produk ditambahkan ke keranjang</div>
 
<!-- State yang tidak tersedia di HTML -->
<button aria-expanded="false" aria-controls="menu">Menu</button>

aria-live="polite" memberi tahu screen reader untuk mengumumkan perubahan (seperti "produk ditambahkan") meski pengguna sedang membaca di tempat lain.

Warning

ARIA tidak mengubah perilaku — ia hanya mengubah informasi yang disampaikan. <div role="button"> tetap tidak bisa ditekan Enter tanpa JavaScript tambahan. Urutan yang benar: HTML semantik dulu, ARIA untuk mengisi celah, jangan ARIA untuk "memperbaiki" struktur yang salah.

Semua interaksi harus bisa dioperasikan keyboard saja:

  • Tab — berpindah fokus antar elemen interaktif.
  • Shift+Tab — mundur.
  • Enter/Space — mengaktifkan tombol.
  • Escape — menutup dialog/menu.
Manajemen fokus dialog
import { useEffect, useRef } from "react";
 
export function Dialog({ onClose }: { onClose: () => void }) {
  const closeBtn = useRef<HTMLButtonElement>(null);
 
  useEffect(() => {
    closeBtn.current?.focus();
    const onKey = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose]);
 
  return (
    <div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
      <h2 id="dialog-title">Keranjang</h2>
      <button ref={closeBtn} onClick={onClose}>Tutup</button>
    </div>
  );
}

Prinsip "nothing is mouse-only": jika sebuah fitur hanya bisa dibuka dengan hover atau drag, fitur itu tidak accessible.

Kontras dan Kejelasan Visual

Kontras teks terhadap latar harus memenuhi WCAG:

  • Teks normal: rasio kontras ≥ 4.5:1.
  • Teks besar (≥24px atau bold ≥18.66px): ≥ 3:1.
  • Elemen UI (ikon, border input): ≥ 3:1.
Cek cepat di DevTools
Elements → pilih teks → klik ikon warna → lihat kontras

Jangan pernah menyampaikan informasi hanya dengan warna (misal: "yang merah berarti salah") — tambahkan ikon atau teks.

Automated A11y Testing

Alat otomatis menangkap 30-50% masalah — penting sebagai jaring awal, bukan pengganti pengujian manual.

Audit dengan axe di browser
# Install ekstensi axe DevTools, lalu:
# Klik "Scan all of my page" pada halaman TokoKita

Di dalam test, integrasikan axe lewat Playwright:

Playwrighta11y.spec.ts
import { test, expect } from "@playwright/test";
 
test("katalog tanpa masalah aksesibilitas otomatis", async ({ page }) => {
  await page.goto("/products");
  const results = await page.evaluate(() =>
    window.axe.run ? window.axe.run(document) : null
  );
  // alternatif praktis: gunakan plugin @axe-core/playwright
});
Component test dengan jest-axe
import { render } from "@testing-library/react";
import { axe } from "jest-axe";
 
it("tidak punya pelanggaran aksesibilitas", async () => {
  const { container } = render(<ProductCard product={product} />);
  expect(await axe(container)).toHaveNoViolations();
});

Praktik: Audit TokoKita

Checklist audit menyeluruh:

  1. Keyboard — jalankan seluruh alur (katalog → keranjang → checkout) dengan Tab saja.
  2. Focus — pastikan fokus terlihat jelas dan tidak "hilang" di dialog.
  3. Screen reader — coba dengan ekstensi (mis. screen reader bawaan) pada heading & form.
  4. Kontras — scan otomatis + cek teks abu-abu di atas abu-abu.
  5. Live regions — pastikan pesan "ditambahkan ke keranjang" diumumkan.
AreaAlatFrekuensi
Static analysisaxe / LighthouseSetiap build (CI)
Component testjest-axeSetiap komponen baru
E2E keyboardPlaywrightAlur kritis
Uji manualPengguna nyata + screen readerSebelum rilis

Tip

Kembangkan "refleks aksesibilitas": setiap kali menulis komponen interaktif, tanya — "apakah ini bisa dioperasikan keyboard? apakah screen reader mendapatkan informasi yang sama?" Refleks ini lebih berharga daripada menghafal daftar teknik.

Penutup

Inti yang harus dibawa pulang:

  • Built-in semantics dulu; ARIA hanya untuk mengisi celah (aria-label, aria-live, aria-expanded).
  • Navigasi keyboard & fokus yang jelas adalah syarat mutlak; jangan ada interaksi mouse-only.
  • Kontras ≥ 4.5:1 untuk teks normal; jangan andalkan warna saja.
  • Otomasi (axe/Lighthouse/jest-axe) sebagai jaring awal, uji keyboard & screen reader secara manual.

Di episode 16 selanjutnya kita menghidupkan antarmuka: animasi & interaction — CSS animations, Web Animations API, dan micro-interactions yang membuat TokoKita terasa hidup tanpa mengorbankan performa. Sampai jumpa di episode 16!

Belajar Frontend - Accessible & Inclusive Design | Belajar Frontend