Memuat...
👋 Selamat Pagi!

Cara Pakai ariaNotify() untuk Notifikasi Aksesibel di Web App

Pelajari cara menggunakan ariaNotify(), API baru WAI-ARIA 1.3 yang bikin notifikasi web app benar-benar aksesibel untuk pengguna screen reader.

Cara Pakai ariaNotify() untuk Notifikasi Aksesibel di Web App

Selama bertahun-tahun, developer yang peduli aksesibilitas harus bergulat dengan aria-live region — sebuah solusi yang fungsional tapi penuh jebakan.

Kamu harus menyuntikkan elemen ke DOM di waktu yang tepat, memastikan region sudah ada sebelum konten dimasukkan, dan berharap screen reader menangkapnya dengan konsisten di semua browser. Hasilnya sering tidak bisa diprediksi.

ariaNotify() hadir untuk mengubah semua itu.

Apa Itu ariaNotify() dan Kenapa Ini Berbeda dari aria-live

ariaNotify() adalah API JavaScript baru yang memungkinkan developer mengirim pesan langsung ke accessibility tree — tanpa perlu memanipulasi DOM sama sekali.

Bukan aria-live. Bukan injeksi elemen tersembunyi. Hanya satu method call yang bersih.

document.ariaNotify("Pesanan kamu berhasil disimpan.");

Sederhana sekali bukan? Tapi di balik kesederhanaannya, ada perubahan paradigma yang signifikan.

Masalah Fundamental aria-live

aria-live memiliki beberapa kelemahan yang sudah dikenal luas:

  • Timing sensitif — elemen harus sudah ada di DOM sebelum konten dimasukkan, kalau tidak, screen reader bisa melewatinya.
  • Konteks bergantung DOM — kalau elemen dihapus dari DOM, pesan hilang begitu saja.
  • Perilaku tidak konsisten — NVDA, JAWS, dan VoiceOver seringkali bereaksi berbeda terhadap aria-live yang sama.
  • Race condition — update terlalu cepat bisa saling "menimpa" tanpa pengguna sempat mendengarnya.

ariaNotify() memotong semua masalah itu dengan berkomunikasi langsung ke accessibility layer di level browser, bukan melalui DOM.

Analogi yang Mudah Dipahami

Kalau aria-live ibarat menaruh catatan di meja dan berharap asisten membacanya, maka ariaNotify() ibarat menelepon asisten secara langsung.

Lebih pasti. Lebih terkontrol. Lebih aksesibel.

Cara Kerja ariaNotify() Berdasarkan Spesifikasi WAI-ARIA 1.3

Spesifikasi WAI-ARIA 1.3 mendefinisikan ariaNotify() sebagai method pada interface Element dan Document.

Signature lengkapnya:

ariaNotify(message: string, options?: AriaNotifyOptions): void;

Parameter AriaNotifyOptions

interface AriaNotifyOptions {
  priority?: "important" | "none";        // default: "none"
  interrupt?: "pending" | "none" | "all"; // default: "pending"
  label?: string;
  notificationId?: string;
}

Mari kita bedah satu per satu.

priority menentukan seberapa mendesak pesan ini.

  • "important" — screen reader akan menginterupsi bacaan yang sedang berjalan dan langsung membacakan pesan ini.
  • "none" — pesan masuk ke antrian dan dibacakan setelah konten saat ini selesai.

interrupt mengontrol bagaimana pesan baru berinteraksi dengan antrian yang sudah ada.

  • "all" — hapus semua pesan yang antri dan langsung baca pesan ini.
  • "pending" — hapus hanya pesan yang belum dibaca, tapi selesaikan yang sedang dibaca.
  • "none" — tambahkan ke antrian tanpa menginterupsi apapun.

notificationId berguna untuk menggantikan notifikasi sebelumnya yang belum dibaca — sangat ideal untuk status update yang terus berubah.

label memberi konteks tambahan yang membantu screen reader mengkategorikan pesan.

Contoh Kombinasi Options

// Pesan error kritis — interupsi segera
document.ariaNotify("Koneksi terputus. Coba lagi.", {
  priority: "important",
  interrupt: "all"
});

// Status update yang bisa digantikan
document.ariaNotify("Upload 45% selesai", {
  priority: "none",
  interrupt: "pending",
  notificationId: "upload-progress"
});

// Notifikasi dengan label kategorisasi
document.ariaNotify("Pesan baru dari Budi", {
  priority: "none",
  label: "Notifikasi Chat"
});

Implementasi Dasar: Toast, Alert, dan Status Update

Mari kita bangun tiga pola notifikasi yang paling umum digunakan.

1. Toast Notification

Toast adalah notifikasi sementara yang muncul sebentar lalu menghilang. Dengan ariaNotify(), kamu bisa memastikan kontennya juga tersampaikan ke pengguna screen reader.

function showToast(message, type = "info") {
  // Tampilkan elemen visual seperti biasa
  const toast = document.createElement("div");
  toast.className = `toast toast--${type}`;
  toast.textContent = message;
  document.body.appendChild(toast);

  // Kirim ke screen reader lewat ariaNotify()
  const priority = type === "error" ? "important" : "none";
  document.ariaNotify(message, { priority });

  // Hapus elemen visual setelah 3 detik
  setTimeout(() => toast.remove(), 3000);
}

// Penggunaan
showToast("Profil berhasil diperbarui!", "success");
showToast("Gagal menyimpan data. Periksa koneksi.", "error");

Perhatikan bahwa elemen visual bisa dihapus kapan saja, tapi screen reader tetap akan membacakan pesan karena ariaNotify() sudah mengirimnya ke accessibility layer.

2. Alert Dialog

Untuk pesan yang membutuhkan perhatian segera:

function triggerAlert(message) {
  document.ariaNotify(message, {
    priority: "important",
    interrupt: "all",
    label: "Peringatan Sistem"
  });
}

// Contoh: sesi hampir berakhir
triggerAlert("Sesi kamu akan berakhir dalam 2 menit. Simpan pekerjaan sekarang.");

3. Status Update Real-Time

Ini adalah use case paling kuat — update status yang terus berubah seperti upload progress atau live search result.

class ProgressAnnouncer {
  constructor(id, label) {
    this.id = id;
    this.label = label;
    this.lastAnnounced = 0;
  }

  update(percent) {
    // Hanya umumkan setiap kelipatan 25% agar tidak bising
    const milestone = Math.floor(percent / 25) * 25;
    if (milestone !== this.lastAnnounced && milestone > 0) {
      document.ariaNotify(`${this.label} ${milestone}% selesai`, {
        priority: "none",
        interrupt: "pending",
        notificationId: this.id
      });
      this.lastAnnounced = milestone;
    }
  }

  complete(finalMessage) {
    document.ariaNotify(finalMessage, {
      priority: "none",
      interrupt: "pending",
      notificationId: this.id
    });
  }
}

// Penggunaan
const uploader = new ProgressAnnouncer("file-upload", "Upload file");
uploader.update(25);  // Akan mengumumkan "Upload file 25% selesai"
uploader.update(50);  // Akan mengumumkan "Upload file 50% selesai"
uploader.complete("File berhasil diunggah.");

Integrasi dengan React dan Laravel Livewire

Integrasi di React

Di React, kamu bisa membungkus ariaNotify() dalam custom hook agar mudah digunakan di seluruh aplikasi.

// hooks/useAriaNotify.js
import { useCallback } from "react";

export function useAriaNotify() {
  const notify = useCallback((message, options = {}) => {
    // Feature detection dulu
    if (typeof document.ariaNotify !== "function") {
      console.warn("ariaNotify() tidak didukung di browser ini.");
      return;
    }
    document.ariaNotify(message, options);
  }, []);

  const notifyImportant = useCallback((message) => {
    notify(message, { priority: "important", interrupt: "all" });
  }, [notify]);

  return { notify, notifyImportant };
}
// components/CheckoutForm.jsx
import { useAriaNotify } from "../hooks/useAriaNotify";

export default function CheckoutForm() {
  const { notify, notifyImportant } = useAriaNotify();

  async function handleSubmit(e) {
    e.preventDefault();

    try {
      await submitOrder();
      notify("Pesanan berhasil dibuat. Cek email kamu untuk konfirmasi.", {
        priority: "none"
      });
    } catch (error) {
      notifyImportant("Pembayaran gagal. Coba metode pembayaran lain.");
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      {/* form fields */}
      <button type="submit">Bayar Sekarang</button>
    </form>
  );
}

Integrasi di Laravel Livewire

Di Livewire, kamu bisa memanfaatkan $dispatch untuk mengirim event ke frontend yang kemudian memanggil ariaNotify().

// app/Livewire/OrderForm.php
class OrderForm extends Component
{
    public function submitOrder()
    {
        try {
            // Proses order...
            $this->dispatch('aria-notify', [
                'message' => 'Pesanan berhasil disimpan.',
                'priority' => 'none'
            ]);
        } catch (\Exception $e) {
            $this->dispatch('aria-notify', [
                'message' => 'Terjadi kesalahan. Coba lagi.',
                'priority' => 'important',
                'interrupt' => 'all'
            ]);
        }
    }
}
// resources/js/app.js atau dalam Alpine.js component
document.addEventListener("livewire:init", () => {
  Livewire.on("aria-notify", ({ message, ...options }) => {
    if (typeof document.ariaNotify === "function") {
      document.ariaNotify(message, options);
    }
  });
});

Dengan pola ini, setiap action dari Livewire component bisa langsung memicu notifikasi yang aksesibel tanpa perlu memikirkan DOM manipulation sama sekali.

Progressive Enhancement: Fallback untuk Browser Lama

Karena ariaNotify() adalah API baru, belum semua browser mendukungnya saat artikel ini ditulis.

Pola yang tepat adalah progressive enhancement — gunakan ariaNotify() kalau tersedia, fallback ke aria-live kalau tidak.

// utils/accessibleNotify.js
let liveRegion = null;

function getLiveRegion() {
  if (!liveRegion) {
    liveRegion = document.createElement("div");
    liveRegion.setAttribute("aria-live", "polite");
    liveRegion.setAttribute("aria-atomic", "true");
    liveRegion.className = "sr-only"; // visually hidden
    document.body.appendChild(liveRegion);
  }
  return liveRegion;
}

export function accessibleNotify(message, options = {}) {
  if (typeof document.ariaNotify === "function") {
    // Gunakan API modern
    document.ariaNotify(message, options);
  } else {
    // Fallback ke aria-live
    const region = getLiveRegion();
    region.setAttribute(
      "aria-live",
      options.priority === "important" ? "assertive" : "polite"
    );
    // Kosongkan dulu, lalu isi — ini memaksa screen reader re-read
    region.textContent = "";
    requestAnimationFrame(() => {
      region.textContent = message;
    });
  }
}
/* CSS untuk visually hidden element */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

Testing Aksesibilitas dengan Screen Reader Nyata

Aksesibilitas tidak bisa hanya diuji dengan automated tools. Kamu perlu testing dengan screen reader sungguhan.

Setup Testing di macOS

VoiceOver sudah built-in di macOS. Aktifkan dengan Command + F5, lalu:

  1. Buka halaman yang ingin diuji di Safari.
  2. Aktifkan VoiceOver dan letakkan fokus di halaman.
  3. Trigger notifikasi dari aplikasimu.
  4. Dengarkan apakah VoiceOver membacakan pesan dengan tepat.

Setup Testing di Windows

NVDA adalah screen reader gratis yang paling banyak digunakan.

  1. Unduh NVDA dari nvaccess.org.
  2. Jalankan NVDA dan buka halaman di Firefox atau Chrome.
  3. Trigger notifikasi dan perhatikan speech output.

Checklist Testing ariaNotify()

Ini poin-poin yang harus diverifikasi:

  • Apakah pesan terbaca tanpa interaksi pengguna?
  • Apakah priority: "important" benar-benar menginterupsi bacaan?
  • Apakah notificationId yang sama berhasil menggantikan notifikasi sebelumnya?
  • Apakah fallback aria-live berjalan benar di browser yang tidak mendukung?
  • Apakah pesan cukup informatif tanpa konteks visual?

Catatan Penting soal Dukungan Browser

Per pertengahan 2026, ariaNotify() sudah masuk fase implementasi di Chromium dan dalam diskusi aktif di Mozilla.

Selalu cek caniuse.com dan MDN Web Docs untuk status dukungan terbaru sebelum deploy ke production.

Kesimpulan

ariaNotify() adalah langkah maju yang signifikan dalam ekosistem aksesibilitas web.

Dia menghilangkan kerumitan aria-live dan memberikan developer cara yang lebih bersih, lebih andal, dan lebih mudah diprediksi untuk berkomunikasi dengan pengguna screen reader.

Kombinasi priority, interrupt, dan notificationId memberi kontrol granular yang selama ini tidak bisa kita miliki hanya dengan atribut HTML.

Mulai adopsi ariaNotify() hari ini dengan pola progressive enhancement — pengguna browser modern dapat pengalaman terbaik, pengguna browser lama tetap terlayani dengan fallback yang solid.

Aksesibilitas bukan fitur tambahan. Ini adalah kualitas dasar aplikasi yang profesional.

Kesulitan dengan tugas programming atau butuh bantuan coding? KerjaKode siap membantu menyelesaikan tugas IT dan teknik informatika Anda. Dapatkan bantuan profesional di jasa tugas IT KerjaKode.

Ajie Kusumadhany
Written by

Ajie Kusumadhany

Founder & Lead Developer KerjaKode. Berpengalaman dalam pengembangan web modern dengan Laravel, React.js, Vue.js, dan teknologi terkini. Passionate tentang coding, teknologi, dan berbagi pengetahuan melalui artikel.

Promo Spesial Hari Ini!

10% DISKON

Promo berakhir dalam:

00 Jam
:
00 Menit
:
00 Detik
Klaim Promo Sekarang!

*Promo berlaku untuk order hari ini

0
User Online
Halo! 👋
Kerjakode Support Online
×

👋 Hai! Pilih layanan yang kamu butuhkan:

Chat WhatsApp Sekarang