Nota: apenas traduzi o texto abaixo e postei aqui.
Um disclosure component é o nome formal do pattern em que você clica em um botão para revelar ou ocultar o conteúdo.
Isso inclui coisas como uma interação "mostrar mais/mostrar menos" para algum texto descritivo abaixo de um vídeo do YouTube ou um menu de hambúrguer que é revelado e ocultado quando você clica nele.
Veremos agora uma maneira de construir disclosure component de forma acessível.
O HTML inicial
Começamos com algum HTML básico.
Incluiremos uma div para nosso conteúdo, com um ID #now-you-see-me. Também adicionaremos um botão que podemos usar para alternar a visibilidade do conteúdo.
<button>Mostrar mais</button>
<div id="now-you-see-me">
Agora você não vê.
</div>
Por razões semânticas, o "toggle" deve ser sempre um botão.
Links implicam para os dispositivos assistivos que clicar neles o levará a algum lugar, enquanto os botões implicam que alguma interatividade é acionada.
Adicionando interatividade
A primeira coisa que precisamos fazer é "listen" quando o botão é clicado, para podermos alternar a visibilidade do nosso conteúdo.
Para começar, vamos usar a event delegation para "listen" eventos de clique.
document.addEventListener('click', function (event) {
// Faça coisas...
});
Somente execute em disclosure buttons
No momento, estamos detectando todos os cliques no document. Precisamos de uma maneira de filtrar todos os cliques que não estejam em nosso toggle button.
Vamos adicionar o atributo data-disclosure ao nosso botão e filtrar os cliques em qualquer elemento que não tenha esse atributo.
<button data-disclosure>Show More</button>
document.addEventListener('click', function (event) {
// Execute apenas em elementos que possuem o atributo [data-disclosure]
// Se event.target não tiver o atributo, return encerra a callback function
if (!event.target.hasAttribute('data-disclosure')) return;
console.log('deu match!');
});
Obtendo nosso conteúdo
Também precisamos de uma forma de associar nosso botão ao conteúdo correspondente. Podemos usar o atributo [aria-controls] para isso.
O atributo [aria-controls] informa aos screen readers que um botão controla o comportamento de outro conteúdo. Você atribui o ID desse conteúdo como o valor do atributo.
<button data-disclosure aria-controls="now-you-see-me">Mostrar mais</button>
Em nosso event listener, podemos obter o valor do atributo aria-controls e passá-lo para document.querySelector() para obter nosso conteúdo.
Precisaremos prefixá-lo com # porque é um seletor de ID.
document.addEventListener('click', function (event) {
// Execute apenas em elementos que possuem o atributo [data-disclosure]
// Se event.target não tiver o atributo, return encerra a callback function
if (!event.target.hasAttribute('data-disclosure')) return;
// Obtêm o conteúdo para toggle
// Se nenhum conteúdo correspondente for encontrado, encerra
// a function com return
var content = document.querySelector('#' + event.target.getAttribute('aria-controls'));
if (!content) return;
console.log(content);
});
Toggling a visibilidade de conteúdo
A última consideração sobre acessibilidade é que o botão também deve ter um atributo [aria-expanded]. Isso informa aos screen readers qual é o estado atual do conteúdo.
Se o atributo [aria-expanded] tiver o valor true, o conteúdo será expandido. Se tiver um valor false, o conteúdo será colapsado.
<button data-disclosure aria-controls="now-you-see-me" aria-expanded="true">Show More</button>
Em nosso script, verificaremos qual é o valor do atributo [aria-expanded].
Se for true, adicionaremos a alteração para false e adicionaremos o atributo [hidden] ao nosso conteúdo para ocultá-lo. Caso contrário, mudaremos para true e removeremos o atributo [hidden] para revelá-lo.
Embora true e false sejam booleanos, o método getAttribute() os retorna como uma string. Precisaremos verificar 'true' como uma string em nosso código.
document.addEventListener('click', function (event) {
// Execute apenas em elementos que possuem o atributo [data-disclosure]
// Se event.target não tiver o atributo, return encerra a callback function
if (!event.target.hasAttribute('data-disclosure')) return;
// Obtêm o conteúdo para toggle
// Se nenhum conteúdo correspondente for encontrado, encerra a function com return
var content = document.querySelector(
'#' + event.target.getAttribute('aria-controls')
);
if (!content) return;
// Se o conteúdo está visível, esconda ele
// Caso contrário, mostre ele
if (event.target.getAttribute('aria-expanded') === 'true') {
event.target.setAttribute('aria-expanded', false);
content.setAttribute('hidden', '');
} else {
event.target.setAttribute('aria-expanded', true);
content.removeAttribute('hidden');
}
});
Agora nosso conteúdo irá realmente aparecer e ocultar quando clicado!
Ocultando conteúdo por default
Atualmente, nosso conteúdo está visível para começar. Em uma application real, provavelmente desejaríamos que eles fossem ocultados por default e revelados quando o botão fosse clicado.
Podemos alterar o valor [aria-expanded] para false e adicionar o atributo [hidden] a todo o nosso conteúdo por default para que tudo seja collapsed desde o início.
<button data-disclosure aria-controls="now-you-see-me" aria-expanded="false">Mostrar mais</button>
<div id="now-you-see-me" hidden>
Agora você não vê.
</div>
Mas... antes que o JavaScript seja carregado e executado, os usuários não poderão expandir o conteúdo.
Você pode clicar no botão, mas nada acontecerá, o que é confuso. E se o arquivo JS falhar por algum motivo, eles nunca poderão visualizar o conteúdo.
Aprimoramento progressivo
Uma pequena pitada de aprimoramento progressivo resolverá isso.
Primeiro, removeremos o atributo [hidden] do nosso conteúdo, mas iremos adicioná-lo aos elementos do botão e manteremos o atributo [aria-expanded] definido como false.
<button
data-disclosure
aria-controls="now-you-see-me"
aria-expanded="false"
hidden
>Mostrar mais</button>
<div id="now-you-see-me">
Agora você não vê.
</div>
Agora, por default, o conteúdo ficará visível, mas o botão ficará oculto.
Quando o JavaScript carrega, queremos mostrar todos os botões e ocultar todo o conteúdo. Usaremos document.querySelectorAll() para obter todos os nossos elementos de botão, encontrar seu conteúdo correspondente e ocultá-lo.
Para melhor suporte do navegador, devemos converter nosso NodeList em um array antes de usar o método Array.forEach().
// Obtêm disclosure buttons
var disclosures = Array.prototype.slice.call(
document.querySelectorAll('[data-disclosure]')
);
// Itera dentro deles com Array.forEach()
disclosures.forEach(function (disclosure) {
// Obtêm o conteúdo associado com o button
var content = document.querySelector(
'#' + disclosure.getAttribute('aria-controls')
);
// Se não há conteúdo, não mostra o button
if (!content) return;
// Mostra o button e esconde o conteúdo
disclosure.removeAttribute('hidden');
content.setAttribute('hidden', '');
});
E com isso, temos um disclosure component acessível e progressivamente aprimorado.
Fonte
Newsletter de Go Make Things
Top comments (0)