Building Accessible Components — UI/UX

Membangun Komponen Accessible Component library yang accessible dari awal menghemat waktu jauh lebih banyak daripada fix di akhir. Prinsipnya: semantic HTML fir

Membangun Komponen Accessible

Component library yang accessible dari awal menghemat waktu jauh lebih banyak daripada fix di akhir. Prinsipnya: semantic HTML first, ARIA only when needed, keyboard always.

Accessible Button

// ✅ Gunakan <button>, bukan <div onClick>
function Button({ children, onClick, disabled, loading }) {
  return (
    <button
      onClick={onClick}
      disabled={disabled || loading}
      aria-busy={loading}
    >
      {loading ? (
        <>
          <span aria-hidden="true">⏳</span>
          <span className="sr-only">Memproses...</span>
        </>
      ) : children}
    </button>
  );
}

Accessible Modal

function Modal({ isOpen, onClose, title, children }) {
  const modalRef = useRef();

  useEffect(() => {
    if (isOpen) {
      // Save previous focus
      const prev = document.activeElement;
      // Focus modal
      modalRef.current?.focus();
      // Restore on close
      return () => prev?.focus();
    }
  }, [isOpen]);

  if (!isOpen) return null;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-labelledby="modal-title"
      ref={modalRef}
      tabIndex={-1}
      onKeyDown={(e) => e.key === "Escape" && onClose()}
    >
      <h2 id="modal-title">{title}</h2>
      {children}
      <button onClick={onClose}>Tutup</button>
    </div>
  );
}

Accessible Form

<form>
  <div>
    <label htmlFor="email">Email</label>
    <input
      id="email"
      type="email"
      required
      aria-describedby="email-hint email-error"
      aria-invalid={hasError}
    />
    <p id="email-hint">Contoh: [email protected]</p>
    {hasError && <p id="email-error" role="alert">Email tidak valid</p>}
  </div>
</form>

Libraries yang Membantu

Checklist per Component