Modal, dialog, caixa ou janela de diálogo e até mesmo pop-up, são os termos mais utilizados para descrever aquelas janelas que aparecem sobrepostas a um conteúdo principal.

Enquanto essas janelas permitem interações mais dinâmicas, para usuários de leitores de tela e que fazem navegação por teclado, elas se tornam pontos inacessíveis se não forem implementadas com acessibilidade.
O principal problema reside no fato de que, ao abrir a janela, o foco do teclado continua na primeira camada de interação, não permitindo que o usuário navegue pelo conteúdo do modal com o teclado. Assim, é preciso que a implementação do mesmo faça também as alterações necessárias de foco independentemente do uso do mouse.
De maneira geral, você deve cuidar para que:
- Com a modal aberta, o foco nunca deve ir para os elementos do fundo;
- O botão de fechar não pode falar apenas “X”, deve conter uma descrição como “Fechar” ou “Cancelar”;
- Ao fechar, o foco deve voltar para o botão ou link que abriu a modal;
A seguir mostraremos alguns passos com pedaços de código exemplo. Esses códigos não constituem uma solução completa de modal acessível. Para isso, verifique nossa listagem de referências ao final da página.
Marque a caixa de diálogo e a sobreposição de caixa de diálogo adequadamente
Ao criar uma caixa de diálogo, precisamos garantir que ela tenha a função apropriada, para isso, determinamos o atributo role com o valor dialog. Também precisamos garantir que haja um rótulo para a caixa de diálogo, fornecido usando os atributos aria-labelledby e opcionalmente a aria-describedby.
Nenhum dos rótulos precisa ser exibido visualmente na tela, desde que estejam na árvore de documentos.
<div class="dialog" role="dialog" aria-labelledby="dialog-title" aria-describedby="dialog-description"> <h1 id="dialog-title">Site Navigation</h1> <p id="dialog-description" class="sr-only">Description goes here</p> <nav> <ul> <li><a href="one.html">Link One</a></li> <li><a href="two.html">Link Two</a></li> <li><a href="three.html">Link Three</a></li> </ul> </nav> <button type="button" aria-label="Close Navigation" class="close-dialog"> <i class="fa fa-times"></i> </button> </div>
Ao abrir a modal, configure o foco
A maneira mais correta e completa em termos de acessibilidade de determinar o foco na abertura do modal consiste em gerar um array de elementos focáveis. Os elementos focáveis são âncoras, campos de formulários, botões e quaisquer elemento que contenha valor de tabindex maior que zero(0). Podemos construir o array com esses elementos com o código abaixo.
function Dialog(dialogEl, overlayEl) {
this.dialogEl = dialogEl;
var focusableEls = this.dialogEl.querySelectorAll('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex="0"]');
this.focusableEls = Array.prototype.slice.call(focusableEls);
}
Então, podemos determinar qual é o primeiro elemento focável e configurar o método focus() para o mesmo.
this.firstFocusableEl = focusableEls[0]; this.firstFocusableEl.focus();
Deve sempre existir ao menos um elemento clicável no modal, mesmo que esse seja o botão de fechar. No entanto, se por algum motivo, você não conseguir gerar o array de elementos clicáveis, pode configurar o foco na janela modal com um código como o a seguir.
showModal() {
...
var modal=document.getElementById('modal2');
modal.focus();
...
}
Ao fechar a modal, volte o foco ao último elemento focado
Redirecionar o foco para o último elemento focado antes da abertura do modal, depois que este é fechado, é importante para que o usuário não precise percorrer todo o caminho que havia percorrido anteriormente com o teclado, não se perca e tenha uma navegabilidade mais consistente em seu site.
Quando abrimos a modal, conseguimos determinar qual elemento disparou sua abertura checando qual elemento está ativo no documento (antes de redirecionar o foco para o modal). Para isso, temos como exemplo o código abaixo, que cria a variável lastFocusedElement para armazenar a referência a tal elemento.
var lastFocusedElement;
function showModal () {
...
// Armazena o último elemento focado
lastFocusedElement=document.activeElement;
var modal=document.getElementById (modalID);
modal.focus ();
...
}
Assim, quando fechamos a modal, conseguimos redirecionar o foco para o elemento focado antes de sua abertura.
function removeModal () {
...
// Retorna o foco para o último elemento focalizado
lastFocusedElement.focus ();
...
}
Previna clicks fora da área da modal enquanto ela estiver aberta
Usuários que navegam pelo teclado não devem poder dar
TABfora do conteúdo da modal
Como uma janela modal restringem visualmente a janela do usuário, usuários de teclado também devem ter a mesma experiência.
Para conseguir isso, precisamos interceptar duas situações
- Se o usuário estiver navegando adiante (pressionando apenas a tecla
TAB) a partir do último elemento focalizável, então precisamos movê-lo para o primeiro elemento focalizável. - Se o usuário estiver andando para trás (pressionando as teclas
SHIFTeTAB) a partir do primeiro elemento focalizável, então precisamos movê-lo para o último elemento focalizável
Se houver apenas um elemento focalizável, evite que ocorra qualquer comportamento quando o usuário pressionar a tecla TAB.
Dialog.prototype.handleKeyDown = function(e) {
var Dialog = this;
var KEY_TAB = 9;
function handleBackwardTab() {
if ( document.activeElement === Dialog.firstFocusableEl ) {
e.preventDefault();
Dialog.lastFocusableEl.focus();
}
}
function handleForwardTab() {
if ( document.activeElement === Dialog.lastFocusableEl ) {
e.preventDefault();
Dialog.firstFocusableEl.focus();
}
}
switch(e.keyCode) {
case KEY_TAB:
if ( Dialog.focusableEls.length === 1 ) {
e.preventDefault();
break;
}
if ( e.shiftKey ) {
handleBackwardTab();
} else {
handleForwardTab();
}
break;
default:
break;
} // end switch
};
Permita que a tecla ESC feche a modal
Dialog.prototype.handleKeyDown = function(e) {
var Dialog = this;
var KEY_TAB = 9;
var KEY_ESC = 27;
switch(e.keyCode) {
case KEY_TAB:
/* Handle if TAB key is pressed (see above) */
case KEY_ESC:
Dialog.close();
break;
default:
break;
} // end switch
};
Referências:
- https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html
- https://bitsofco.de/accessible-modal-dialog/
- https://developers.google.com/web/fundamentals/accessibility/focus/using-tabindex?hl=pt-br
- https://tableless.com.br/comecando-wai-aria-janela-modal/
- https://www.maujor.com/tutorial/escrevendo-javascript-com-acessibilidade-em-mente.php