Criando componentes para Web #01: Acessibilidade (a11y) na prática com WAI-ARIA
Tags: frontend, a11y, webdev, html
Published: 2024-06-16 16:28:03

<audio format>

## O que abordaremos nessa série?

Olá, nessa série de artigos vamos abordar todos as especialidades que uma pessoa profissional de Front-End precisa compreender para criar componentes **acessíveis**, **performáticos**, **responsivos**, **manuteníveis**, **reutilizáveis**, **documentados**, **customizáveis**, **testados** e que atendem as reais necessidades de produtos e times de desenvolvimento, independente da tecnologia escolhida, seja **React.js**, **Angular**, **Vue.js** ou qualquer outra.

## Como vamos abordar cada assunto?

Pensei em seguirmos um roteiro para que cada assunto possa ser abordado com o mesmo padrão, dessa forma não perdemos nenhum ponto importante e ainda me ajuda na hora de escrever hehe.

### Roteiro genérico:

- Introdução
- Qual a importância?
- Principais referências
- Aplicando na prática
- Como testar
- Dicas de especialista
- Próximos passos

Ok, agora que estamos alinhados com as ideias por trás dessa série, vamos partir para o primeiro assunto. Bem vindos ao mundo da **a11y** ❤️.

## Introdução

Primeiro precisamos entender o que significa o tal **a11y**. Basicamente é a abreviação da palrava em inglês **accessibility** (acessibilidade), sendo **a + 11 letras no meio + y**. Apenas abreviamos o termo para facilitar o uso no dia a dia.

> **Dica**: Fazemos o mesmo com a palavra **internationalization** (internacionalização), sendo **i + 18 letras no meio + n**, logo temos como resultado o tão famoso termo **i18n** (Que será assunto de um próximo artigo).

Dentre todos os aspectos relacionados a acessibilidade web, hoje abordaremos o famoso **WAI-ARIA**, mas antes, precisamos conhecer a **WAI**.

**WAI** ou **[Web Accessibility Initiative](https://www.w3.org/WAI/)** (Iniciativa de Acessibilidade na Web), é uma iniciativa da [W3C](https://www.w3.org) para desenvolver padrões e materiais de apoio que nos ajudam a compreender e implementar a acessibilidade.

Já o **[WAI-ARIA](https://www.w3.org/WAI/standards-guidelines/aria/)** nós podemos definir como uma especificação que traz uma extensão para o `HTML`, adicionar muito mais dinamismo e controle sobre a semântica.

### Qual a importância da a11y?

Antes de demonstrar o **WAI-ARIA** em ação, e para nivelar o conhecimento, precisamos abordar a importância da acessibilidade na web, e para isso, eu trouxe alguns links de experts que já explicaram  muito bem o assunto na comunidade Front-End ❤️.

### Referências sobre a11y na Web

- @brunopulis: [Acessibilidade Web: como começar do jeito certo](https://brunopulis.com/introducao-acessibilidade-web/)
- [Talita Pagani](http://talitapagani.com): [Acessibilidade na prática para você nunca mais esquecer](https://www.youtube.com/watch?v=4URTZHk6tz0&t=129s)
- [Reinaldo Ferraz](https://reinaldoferraz.com.br): [Acessibilidade na web modo Jedi Master](https://www.youtube.com/watch?v=MMLQioPwbik)

## Aplicando na prática

Antes de aplicarmos o **WAI-ARIA**, para que tudo faça sentido precisamos entender de forma prática a importância da semântica e ir muito além de simplesmente dizer que "`HTML` semântico é o certo", sem um critério objetivo.

Vamos começar com um simples componente de `toggle button`, e para facilitar o exemplo vamos trabalhar apenas com `HTML` + `CSS` + `JS`:

```html
<span class="toggle">
  <span> OFF </span>
  <button class="toggle__button"></button>
  <span> ON </span>
</span>
```
Resultado:

![Exemplo de toggle button, sendo clicado e alternando o estado de clicado e não clicado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehjxkiryoydl01mv918q.gif)

> PS: O código completo desse exemplo, incluindo CSS e Javascript, pode ser acessado no [meu Codepen](https://codepen.io/afonsopacifer/pen/dyEVmeJ).

Conseguem perceber os graves problemas de semântica dessa botão? Não?

Do ponto de vista de um usuário comum, o comportamento está bem claro e bem fácil de entender, mas a semântica não foi feita para um usuário "comum".

A principal função da semântica no `HTML` é ser interpretada por robôs, sejam mecanismos de busca (tentando entender sua página para rankea-la) ou leitores de tela (transcrevendo o conteúdo, iterações e estados para um usuário com deficiência visual).

O **WAI-ARIA** em especial é extremamente importante para adicionar significado para a interface através da semântica, afinal, entender que uma interface na web não é algo apenas visual, faz parte das bases para um pessoa verdadeiramente profissional em Front-End.

Para ficar mais claro, vamos testar esse botão com um software leitor de tela e analisar os resultados:

{% youtube https://www.youtube.com/watch?v=FfQu6iQwuNQ %}

Como podemos perceber, o `toggle-button` não indica o estado de `ON` ou `OFF`, em outras palavras, não sabemos se o botão está clicado ou não.

Para corrigir isso, podemos adicionar a propriedade `aria-pressed`, que tem como valores possíveis: 

- `true`: para indicar que está "clicado".
- `false`: indicando que "não esta clicado".
- `mixed`: para indicar que está entre os dois estados.

```html
<span class="toggle">
  <span> OFF </span>
  <button class="toggle__button" aria-pressed="false"></button>
  <span> ON </span>
</span>
```

Resultado:

{% youtube https://www.youtube.com/watch?v=w1-YzKW5MtQ %}

Bem melhor, porém ainda temos um grave problema na experiência do usuário. Apesar do comportamento do botão estar claro, como não existe conteúdo de texto dentro do elemento `button`, não é possível saber o que o botão faz, a única informação que o leitor de tela tem é um `toggle-button` sem descrição.

Vamos adicionar um `aria-label` para resolver esse problema.

```html
<span class="toggle">
  <span> OFF </span>
  <button
    class="toggle__button"
    aria-pressed="false"
    aria-label="Alterna entre os modos ON e OFF">
  </button>
  <span> ON </span>
</span>
```

Resultado:

{% youtube https://www.youtube.com/watch?v=fKK7igcqRmg %}

Ainda podemos ir além, caso o `toogle-button` abra `dropdown`, podemos vincular os componentes usando o atributo `aria-haspopup`, e assim por diante.

Na categoria **States and Properties** (Estados e propriedades) do **WAI-ARIA**, temos uma longa lista de atributos possíveis para adicionar semântica em nossas aplicações, recomendo a consultar a [lista completa na documentação da Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes).

### Indo além com `WAI-ARIA Roles`

Quando falamos em componentes, na maioria das vezes criamos elementos que não existem no `HTML`, e mesmo quando existem, é bem comum ignorar o elemento nativo e criar um comportamento personalizado, como exemplo ignorar a tag `<dialog>`e criar um `modal` do zero utilizando apenas `<div>`. Não há nada de errado com essa pratica, desde que deixe claro para o leitor de tela que o papel (em inglês: **role**) daquela `<div>` é se comportar como `modal`, ai entram os atributos da categoria **WAI-ARIA Roles**.

### Vamos nos aprofundar com um exemplo mais crítico

Sabe quando utilizamos elementos semânticos do HTML para construir algo? Podemos, por exemplo, criar a estrutura de uma página da seguinte forma não semântica:

```html
<div>
  <div></div>
  <div>
    <div></div>
    <div></div>
  </div>
  <div></div>
</div>
```

Ou seguindo um `HTML` semântico:

```html
<div>
  <header></header>
  <main>
    <section></section>
    <section></section>
  </main>
  <footer></footer>
</div>
```

Até aí tudo bem, aprendemos que devemos escrever de forma semântica e os motivos da sua importância. Mas e quando não encontramos uma tag `HTML` perfeita para nossa necessidade? Ai entra o atributo `role`.

Vamos ao exemplo de um alerta de erro:

```html
<div class="snackbar-error">
  Ouve um problema ao enviar sua solicitação
</div>
```

Parando para pensar com calma, entendemos que simplesmente jogar um alerta visual na tela não alerta um usuário de leitor de tela, certo?

Para que o papel de alerta seja realizado corretamente pelo componente, precisamos adicionar esse papel:

```html
<div class="snackbar-error" role="alert">
  Ouve um problema ao enviar sua solicitação
</div>
```

Dessa forma o leitor de tela avisa ao usuário que existe um alerta e lê a mensagem assim que o alerta for disparado ❤️.

Mais uma vez eu recomendo consultar a lista completa de `roles` na [documentação da Mozilla Developer Network ](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles).

## Como testar

Nos exemplos acima, eu usei o leitor de tela chamado **Voice Over**, que já vem instalado por padrão nos computadores com sistema operacional **macOS**, mas obviamente existem leitores de tela para **Windows**, **Linux**, **Android**, etc... Recomendo pesquisar, instalar e aprender bem a usar ao menos um leitor de tela, afinal, seria no mínimo estranho projetar interfaces visuais sem monitor, logo, pensar em semântica sem se quer testar o que você esta fazendo, beira o absurdo! (desculpem a falta de decoro, me exaltei rsrsrs).

## Dicas de especialista

- Na hora de criar um componente, não pule etapas por achar que `HTML` é simples. Planeje a semântica, pesquise e teste.

- Durante sua analise de requisitos, crie uma tarefa para pesquisar e construir a semântica do componente antes mesmo de começar a trabalhar no `CSS`.

- Tente [recriar um botão sem usar a tag `<button>`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role), o aprendizado vai trazer bons insights, confia.

## Conclusão

Lembre-se! Se você se considera uma pessoa boa com `HTML`, mas nunca abriu um leitor de tela, repense, saber como o `HTML` funciona e ser profissional são coisas diferentes.

Ah, se você gostou do conteúdo e quer que essa série continue, comente com um feedback e compartilhe com seus amigos Devs.

E claro! Me siga para mais dicas 😎:

- [Meu site pessoal](https://afonsopacifer.github.io)
- [Github](https://github.com/afonsopacifer)
- [Twitter](https://x.com/afonsopacifer)
- [Linkedin](https://www.linkedin.com/in/afonsopacifer/)
- [Instagram](https://www.instagram.com/afonsopacifer/)

Obrigado por ler e te vejo na próxima ❤️.