0Pricing
React Academy · Lekcja

Obsługa fokusu i pułapek klawiatury w modalach

Utrzymuj fokus wewnątrz otwartych modali dla zapewnienia dostępności, korzystając z useRef i nasłuchiwania zdarzeń

Obsługa fokusu i pułapek klawiatury w modalach to bezpłatna lekcja React Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej React Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs React Academy zawiera 4 lekcji w sumie.

Witamy

W tej lekcji zaimplementują Państwo pułapkę fokusu wewnątrz modala, aby użytkownicy klawiatury nie mogli wyjść klawiszem Tab poza otwarty modal — jest to kluczowy wymóg dostępności (WCAG 2.4.3).

Dlaczego pułapki fokusu są wymagane

Po otwarciu modala użytkownicy klawiatury powinni móc korzystać wyłącznie z jego zawartości. Bez pułapki fokusu naciśnięcie Tab przenosi fokus na elementy znajdujące się za nakładką modala — są one niewidoczne, ale nadal dostępne.

Czym jest pułapka fokusu

Pułapka fokusu przechwytuje zdarzenia klawiszy Tab i Shift+Tab, a gdy fokus miałby opuścić modal, przenosi go z powrotem na pierwszy lub ostatni element możliwy do zogniskowania wewnątrz modala.

Wyszukiwanie elementów możliwych do zogniskowania

Należy użyć querySelectorAll z selektorem obejmującym wszystkie elementy interaktywne. Należy odfiltrować elementy wyłączone i ukryte.
const FOCUSABLE = [
  'a[href]', 'button:not([disabled])',
  'input:not([disabled])', 'select', 'textarea',
  '[tabindex]:not([tabindex="-1"])'
].join(',');

const focusable = Array.from(
  modalRef.current.querySelectorAll(FOCUSABLE)
);

Implementowanie pułapki

Należy nasłuchiwać zdarzenia keydown na kontenerze modala. Po naciśnięciu Tab, jeśli fokus znajduje się na ostatnim elemencie, należy przenieść go na pierwszy. Po naciśnięciu Shift+Tab, jeśli fokus znajduje się na pierwszym elemencie, należy przenieść go na ostatni.
function handleTab(e) {
  const focusable = /* array of focusable elements */;
  const first = focusable[0];
  const last = focusable[focusable.length - 1];
  if (e.key !== 'Tab') return;
  if (e.shiftKey) {
    if (document.activeElement === first) {
      e.preventDefault(); last.focus();
    }
  } else {
    if (document.activeElement === last) {
      e.preventDefault(); first.focus();
    }
  }
}

Przenoszenie fokusu po otwarciu

Po otwarciu modala należy przenieść fokus na pierwszy element możliwy do zogniskowania wewnątrz niego (lub na sam kontener modala za pomocą `tabIndex=-1`). Zapobiega to pozostaniu fokusu na przycisku, który otworzył modal.
useEffect(() => {
  if (isOpen) {
    const first = modalRef.current?.querySelector(FOCUSABLE);
    first?.focus();
  }
}, [isOpen]);

Przywracanie fokusu po zamknięciu

Po zamknięciu modala należy przywrócić fokus na element, który był aktywny przed jego otwarciem. W chwili otwarcia modala należy zapisać referencję do `document.activeElement`.
const previousFocus = useRef(null);

useEffect(() => {
  if (isOpen) {
    previousFocus.current = document.activeElement;
  } else {
    previousFocus.current?.focus();
  }
}, [isOpen]);

Używanie biblioteki focus-trap-react

W zastosowaniach produkcyjnych warto rozważyć bibliotekę **focus-trap-react**. Obsługuje ona wszystkie przypadki brzegowe: shadow DOM, ramki iframe, dynamicznie dodawane elementy możliwe do zogniskowania oraz dezaktywację po naciśnięciu Escape.
import FocusTrap from 'focus-trap-react';

{isOpen && (
  <FocusTrap>
    <div role="dialog" aria-modal="true">
      {children}
    </div>
  </FocusTrap>
)}

Atrybuty ARIA dla modali

Do kontenera modala należy dodać `role="dialog"` i `aria-modal="true"`. Należy dodać `aria-labelledby` wskazujący nagłówek modala. Informuje to czytniki ekranu, że element jest modalnym oknem dialogowym, i pozwala go poprawnie zapowiedzieć.
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">Confirm Delete</h2>
  ...
</div>

Atrybut inert dla tła

Atrybut HTML `inert` na kontenerze usuwa wszystkie jego elementy z kolejności fokusu i dostępności dla czytników ekranu. Gdy modal jest otwarty, należy ustawić `document.getElementById('root').inert = true`, aby skutecznie zablokować tło.
useEffect(() => {
  const root = document.getElementById('root');
  if (isOpen) root.setAttribute('inert', '');
  else root.removeAttribute('inert');
}, [isOpen]);

Szybkie sprawdzenie

Co powinno się stać, gdy użytkownik klawiatury naciśnie Tab na ostatnim elemencie możliwym do zogniskowania w modalu z pułapką fokusu?

Podsumowanie

Zaimplementowali Państwo pułapkę fokusu: wyszukali elementy możliwe do zogniskowania, przechwycili Tab/Shift+Tab, przenieśli fokus po otwarciu i przywrócili go po zamknięciu. W zastosowaniach produkcyjnych należy używać focus-trap-react oraz dodać role='dialog' i aria-modal dla czytników ekranu.

Następny temat

Następna lekcja: **Tooltips & Dropdown Menus with Portals** — wyrenderują Państwo podpowiedzi i menu rozwijane, które za pomocą createPortal wydostają się poza kontenery z overflow-hidden.

Często zadawane pytania

Czy lekcja „Obsługa fokusu i pułapek klawiatury w modalach” jest bezpłatna?

Tak — pełny tekst „Obsługa fokusu i pułapek klawiatury w modalach” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu React Academy, przejdź na CoddyKit PRO. Kurs React Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Obsługa fokusu i pułapek klawiatury w modalach”?

Utrzymuj fokus wewnątrz otwartych modali dla zapewnienia dostępności, korzystając z useRef i nasłuchiwania zdarzeń Ćwiczysz React Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć React Academy?

Nie wymagamy żadnego doświadczenia. React Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Obsługa fokusu i pułapek klawiatury w modalach”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji React Academy?

Tak. Każda lekcja React Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Czym są React Portals?
  2. Budowanie komponentu modalnego za pomocą portali
  3. Obsługa fokusu i pułapek klawiatury w modalach
  4. Tooltipy i menu rozwijane za pomocą portali
← Powrót do React Academy