Keyboard Navigation
Banyak user bergantung pada keyboard: pengguna screen reader, power user, orang dengan motor disabilities. Setiap UI interaktif harus bisa dioperasikan sepenuhnya dengan keyboard.
Focus Management
/* Visible focus indicator — WAJIB */
:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
/* Jangan pernah: */
*:focus { outline: none; } /* ← ini membuat keyboard user buta */
Tab Order
tabindex="0"— Masukkan elemen ke tab order naturaltabindex="-1"— Focusable via JS, tapi tidak di tab ordertabindex="1+"— HINDARI. Mengacaukan natural order.
Common Keyboard Patterns
// Focus trap (modal)
// Tab di elemen terakhir → kembali ke elemen pertama
function trapFocus(modal) {
const focusable = modal.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const first = focusable[0];
const last = focusable[focusable.length - 1];
modal.addEventListener("keydown", (e) => {
if (e.key === "Tab") {
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
if (e.key === "Escape") closeModal();
});
}
Roving Tabindex (Toolbar, Tabs)
// Hanya satu item di tab order pada satu waktu
// Arrow keys pindah fokus antar item
<div role="tablist">
<button role="tab" tabindex="0">Tab 1</button>
<button role="tab" tabindex="-1">Tab 2</button>
<button role="tab" tabindex="-1">Tab 3</button>
</div>
// ArrowRight → fokus Tab 2 (tabindex="0"), Tab 1 jadi tabindex="-1"
Skip Links
<!-- Elemen pertama di body -->
<a href="#main-content" class="skip-link">
Langsung ke konten utama
</a>
<!-- Visible on focus, hidden otherwise -->