0Pricing
React Academy · Aula

Tratamento de foco e armadilhas de teclado em modais

Mantenha o foco dentro de modais abertos para acessibilidade usando useRef e ouvintes de eventos.

Tratamento de foco e armadilhas de teclado em modais é uma aula grátis de React Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de React Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de React Academy inclui 4 aulas no total.

Boas-vindas

Nesta lição, você implementará uma armadilha de foco dentro de um modal para que usuários do teclado não possam sair de um modal aberto usando Tab — um requisito essencial de acessibilidade (WCAG 2.4.3).

Por que as armadilhas de foco são obrigatórias

Quando um modal é aberto, os usuários do teclado devem poder interagir somente com o conteúdo do modal. Sem uma armadilha de foco, pressionar Tab move o foco para elementos atrás da sobreposição do modal — esses elementos ficam visualmente ocultos, mas continuam acessíveis.

O que é uma armadilha de foco

Uma armadilha de foco intercepta os eventos de teclado Tab e Shift+Tab e, quando o foco sairia do modal, faz com que ele volte para o primeiro ou último elemento focusable dentro do modal.

Encontrando elementos focusable

Use querySelectorAll com um seletor que abranja todos os elementos interativos. Filtre os elementos desabilitados e ocultos.
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)
);

Implementando a armadilha

Escute o evento keydown no contêiner do modal. Ao pressionar Tab, se o foco estiver no último elemento, mova-o para o primeiro. Ao pressionar Shift+Tab, se o foco estiver no primeiro, mova-o para o último.
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();
    }
  }
}

Movendo o foco ao abrir

Quando o modal abrir, mova o foco para o primeiro elemento focusable dentro dele (ou para o próprio contêiner do modal com `tabIndex=-1`). Isso impede que o foco permaneça no botão que abriu o modal.
useEffect(() => {
  if (isOpen) {
    const first = modalRef.current?.querySelector(FOCUSABLE);
    first?.focus();
  }
}, [isOpen]);

Restaurando o foco ao fechar

Quando o modal fechar, devolva o foco ao elemento que estava ativo antes de o modal ser aberto. Armazene uma referência a document.activeElement no momento em que o modal abrir.
const previousFocus = useRef(null);

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

Usando a biblioteca focus-trap-react

Para uso em produção, considere a biblioteca **focus-trap-react**. Ela lida com todos os casos extremos: DOM sombreado, quadros incorporados, elementos focusable adicionados dinamicamente e desativação ao pressionar Escape.
import FocusTrap from 'focus-trap-react';

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

Atributos ARIA para modais

Adicione `role="dialog"` e `aria-modal="true"` ao contêiner do modal. Adicione `aria-labelledby` apontando para o título do modal. Isso informa aos leitores de tela que o diálogo é um modal e faz com que ele seja anunciado corretamente.
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">Confirm Delete</h2>
  ...
</div>

Atributo inert para o plano de fundo

O atributo `inert` do HTML em um contêiner remove todos os seus elementos da ordem de foco e da acessibilidade dos leitores de tela. Defina `document.getElementById('root').inert = true` enquanto o modal estiver aberto para bloquear o plano de fundo de forma robusta.
useEffect(() => {
  const root = document.getElementById('root');
  if (isOpen) root.setAttribute('inert', '');
  else root.removeAttribute('inert');
}, [isOpen]);

Verificação rápida

O que deve acontecer quando um usuário do teclado pressiona Tab no último elemento focusable dentro de um modal com armadilha de foco?

Recapitulação

Você implementou uma armadilha de foco: encontrou elementos focusable, interceptou Tab/Shift+Tab, moveu o foco ao abrir e o restaurou ao fechar. Use focus-trap-react em produção e adicione role='dialog' e aria-modal para os leitores de tela.

A seguir

Próxima lição: **Dicas de ferramenta e menus suspensos com portais** — você renderizará dicas de ferramenta e menus suspensos que escapam de contêineres com overflow oculto usando createPortal.

Perguntas Frequentes

A aula “Tratamento de foco e armadilhas de teclado em modais” é grátis?

Sim — o texto completo de “Tratamento de foco e armadilhas de teclado em modais” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de React Academy, atualize para CoddyKit PRO. O curso de React Academy inclui 4 aulas no total.

O que vou aprender em “Tratamento de foco e armadilhas de teclado em modais”?

Mantenha o foco dentro de modais abertos para acessibilidade usando useRef e ouvintes de eventos. Você pratica React Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar React Academy?

Nenhuma experiência prévia é necessária. React Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Tratamento de foco e armadilhas de teclado em modais”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de React Academy?

Sim. Cada aula de React Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. O que são os Portals do React
  2. Criação de um componente modal com Portals
  3. Tratamento de foco e armadilhas de teclado em modais
  4. Dicas de ferramentas e menus suspensos com Portals
← Voltar para React Academy