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)