FluentStack

Modal Accessibility

Mode tersedia: dark, light, paper
MasukDaftar
Advanced · Level 15: AccessibilityAdvanced65 menitBahasa Indonesia

Modal Accessibility

Membuat modal kecil dengan label yang jelas, focus entry, close behavior, focus containment, dan focus return.

StatusMemuat progres
ProgresMemuat...

...

Memuat progres

Menyiapkan langkah berikutnya

Tujuan belajar

  • Menjelaskan modal sebagai interaction yang sementara mengambil perhatian user
  • Memberi label dialog, close action, dan Escape behavior yang jelas
  • Memindahkan serta menahan focus pada dialog kecil dengan control terbatas
  • Mengembalikan focus ke trigger saat modal ditutup
ReactModalFocus ManagementKeyboard NavigationARIA

Isi lesson

6 blok
  1. 1.
    Modal bukan sekadar card di atas pageBelum selesaiWajib
  2. 2.
    Dialog konfirmasi kecil dengan focus loop yang terbatasBelum selesaiWajib
  3. 3.
    Coding practiceBelum selesaiWajib
  4. 4.
    Cek pemahamanBelum selesaiWajib
  5. 5.
    Dialog sederhana tidak otomatis menjadi pattern universalBelum selesaiWajib
  6. 6.
    RingkasanBelum selesaiWajib

Modal bukan sekadar card di atas page

Wajib

Modal menghentikan journey sementara untuk meminta keputusan, input, atau konfirmasi. Karena content di belakangnya tidak lagi menjadi konteks utama, focus harus masuk ke dialog saat dibuka, tetap berada di dalam dialog selama dialog modal aktif, dan kembali ke trigger atau langkah workflow yang tepat setelah ditutup. Dialog juga perlu nama yang jelas serta close action yang terlihat. Menambahkan role dialog saja tidak memberi semua behavior tersebut. Pada latihan ini kita membangun dialog kecil dengan dua control agar pola focus dapat dibaca. Untuk dialog production yang memiliki form, scrolling, atau banyak control, gunakan pattern yang telah diuji dan lakukan keyboard review lebih luas.

Bagian ini memengaruhi progres lesson.

Dialog konfirmasi kecil dengan focus loop yang terbatas

Wajib
tsx
import { useRef, useState } from "react";

export function LeaveLessonDialog() {
  const [isOpen, setIsOpen] = useState(false);
  const triggerRef = useRef<HTMLButtonElement>(null);
  const closeRef = useRef<HTMLButtonElement>(null);
  const leaveRef = useRef<HTMLButtonElement>(null);

  function openDialog() {
    setIsOpen(true);
    window.setTimeout(() => closeRef.current?.focus(), 0);
  }

  function closeDialog() {
    setIsOpen(false);
    window.setTimeout(() => triggerRef.current?.focus(), 0);
  }

  return (
    <section>
      <button ref={triggerRef} type="button" onClick={openDialog}>
        Keluar dari lesson
      </button>
      {isOpen ? (
        <div
          role="dialog"
          aria-modal="true"
          aria-labelledby="leave-dialog-title"
          onKeyDown={(event) => {
            if (event.key === "Escape") closeDialog();
          }}
        >
          <h2 id="leave-dialog-title">Keluar dari lesson?</h2>
          <button
            ref={closeRef}
            type="button"
            onClick={closeDialog}
            onKeyDown={(event) => {
              if (event.key === "Tab" && event.shiftKey) {
                event.preventDefault();
                leaveRef.current?.focus();
              }
            }}
          >
            Tetap belajar
          </button>
          <button ref={leaveRef} type="button" onKeyDown={(event) => {
            if (event.key === "Tab" && !event.shiftKey) {
              event.preventDefault();
              closeRef.current?.focus();
            }
          }}>
            Keluar
          </button>
        </div>
      ) : null}
    </section>
  );
}

Dialog diberi nama lewat aria-labelledby, focus masuk ke close action setelah modal muncul, dan focus kembali ke trigger setelah close. Contoh ini hanya memiliki dua button sehingga loop Tab dapat ditunjukkan secara eksplisit. Dialog nyata membutuhkan review seluruh tabbable element, Shift+Tab, Escape, background inert, scroll, dan pilihan focus awal yang sesuai isi dialog.

Bagian ini memengaruhi progres lesson.

Coding practice

WajibDibuka di workspace khusus

Improve leave lesson dialog

Lengkapi modal konfirmasi agar memiliki label, focus entry, Escape, close action, focus loop kecil, dan focus return.

Tujuan awal: Fokus di tab TSX.

Practice ini dibuka di workspace khusus. Buka practice untuk memakai editor, preview, dan cek otomatis.

Tombol selesai aktif setelah semua validasi wajib lolos.

9 cek otomatis5 checklist
Belum selesaiBuka practice

Cek pemahaman

WajibJawab dulu

Cek pemahaman singkat

Saat modal konfirmasi dibuka dari button Keluar dari lesson, focus awal yang paling masuk akal untuk dialog kecil adalah

Progres lesson naik setelah jawaban benar.

Peringatan

Wajib

Dialog sederhana tidak otomatis menjadi pattern universal

Jangan menyalin focus loop dua button ini untuk dialog panjang atau component library besar. Dialog dengan input, list, atau dynamic content membutuhkan perhitungan tabbable element yang lebih lengkap. Gunakan pattern yang teruji, lalu review behavior dengan keyboard dan screen reader pada project nyata.

Bagian ini memengaruhi progres lesson.

Ringkasan

Wajib
  • Modal perlu nama, close action, focus entry, dan focus return yang dapat diuji.
  • Modal dialog menahan Tab dan Shift+Tab di dalam dialog selama aktif.
  • Escape umumnya menutup dialog bila tidak bertentangan dengan workflow penting.
  • Role ARIA tanpa focus behavior belum membuat modal dapat dipakai keyboard.
  • Berikutnya, dropdown dibaca dari tujuan interaction agar kita tidak memakai menu pattern kompleks untuk daftar link biasa.

Bagian ini memengaruhi progres lesson.

Langkah berikutnya

Selesaikan bagian penting lesson ini

Lanjutkan blok wajib berikutnya: Modal bukan sekadar card di atas page.