Alura > Cursos de Front-end > Cursos de React > Conteúdos de React > Primeiras aulas do curso React: acessibilidade para desenvolver interfaces inclusivas

React: acessibilidade para desenvolver interfaces inclusivas

Caixas de seleção - Apresentação

Olá! Tudo bem? Eu sou o Neilton Seguins, mas pode me chamar de Nei.

Audiodescrição: Neilton se descreve como um homem cis, de pele preta, cabelos curtos e encaracolados pretos, e olhos castanho-escuros. Ele usa um óculos com armação retangular e veste uma camisa amarela. Ao fundo, há uma parede lisa com iluminação em degradê azul e rosa.

Estamos muito felizes de estar com você neste curso de React, onde falaremos sobre acessibilidade em Single Page Applications (Aplicações de Página Única), ou SPAs.

O que vamos aprender?

Partiremos de uma aplicação chamada Zoop, um e-commerce de varejo que vende diversos produtos, e ela já tem uma base da aplicação.

Portanto, você vai receber essa aplicação pronta e vamos trabalhar em cima dela, na questão de melhorar a acessibilidade de alguns componentes e também criar outros, como, por exemplo, um componente de modal, que sempre é um dos vilões da acessibilidade.

É muito difícil trabalhar com componentes de modal, porque ele fica por cima de outros elementos da página, e precisamos controlar um pouco o foco para mantê-lo dentro da modal, entre outras coisas.

Vamos criar também um componente de acordeão, considerado outro vilão da acessibilidade. Precisamos entender como controlar esse componente, os estados dele de aberto e fechado, e muito mais.

Pré-requisitos

Para começar neste curso, você precisa ter uma base de React com TypeScript, porque o TypeScript será nosso aliado. Ele vai nos auxiliar muito e isso vai ser o suficiente.

Você também deve saber um pouco sobre acessibilidade na web. Se você não tem essa base, recomendamos fazer a formação disponível na plataforma e depois retornar para este curso.

Conclusão

Gostaríamos de te convidar para participar da nossa comunidade no Discord, um ambiente onde você pode se desenvolver, fazer networking, participar de eventos que acontecem todos os dias e semanas, e estar em contato com pessoas instrutoras, estudantes e até convidadas.

Vamos dar início a este curso e trocar muita ideia sobre acessibilidade na web, principalmente no React!

Caixas de seleção - Criando um Checkbox acessível

Quando falamos de acessibilidade em aplicações web, nos referimos a escrever um código que permita uma experiência na internet acessível para todos os tipos de pessoas, tanto pessoas consideradas típicas quanto pessoas com deficiência.

Existem pessoas que têm necessidades como utilizar leitores de tela, ou até mesmo teclados especializados para navegar em sites. Portanto, a experiência delas é diferente de pessoas consideradas típicas, que utilizam bastante o mouse e outros recursos.

Assim, quando falamos de acessibilidade, nosso objetivo é criar uma aplicação que seja navegável e usual, tanto para pessoas com deficiência quanto para pessoas consideradas típicas.

Criando um checkbox acessível

Na internet, encontramos elementos que já têm um comportamento padrão. Vamos analisar um exemplo: com o Google Chrome aberto, acessaremos o Figma do projeto em que vamos trabalhar.

No Figma, temos todos os componentes da aplicação, organizados graças à designer Isa, que já deixou tudo preparado. Nessa aplicação, há um componente de checkbox (caixa de seleção) que está na página de produto, e podemos marcá-lo se quisermos uma garantia para determinado produto.

Os componentes de checkbox são naturalmente acessíveis. Conseguimos interagir com eles, marcá-los e desmarcá-los para serem ativados ou desativados.

Porém, no React, precisamos controlar esses componentes, o que chamamos de componentes controlados. Precisamos criar um estado para o componente e fazer o controle. Como o objetivo é desenvolver uma aplicação mais acessível, vamos criar esse componente de checkbox agora.

Instalando as dependências

Vamos abrir o Visual Studio Code, onde a aplicação já está em execução, no começo do projeto deste curso. Você deve baixar e instalar as dependências com o comando npm install.

npm install

Não vamos passar por esse processo, porque se trata de uma aplicação React criada em Vite e também com TypeScript. No decorrer do curso, você perceberá que o TypeScript será muito útil.

Criando o arquivo checkbox.tsx

No diretório "src", temos a pasta "componentes", que já contém outra pasta chamada "Checkbox". Por enquanto, essa pasta tem apenas um arquivo chamado Checkbox.css.

Vamos criar nessa pasta um novo arquivo chamado Checkbox.tsx. Feito isso, vamos importar na primeira linha o arquivo Checkbox.css, escrevendo import e, entre aspas simples, o nome do arquivo.

Checkbox.tsx:

import "./Checkbox.css";

Assim, importamos os nossos estilos para o novo componente.

Construindo o componente Checkbox

Com o atalho rafce, de uma extensão que usamos e vamos apresentar mais adiante, criaremos um reactArrowFunctionExportComponent, componente que recebe uma arrow function (função de seta).

Ao pressionar "Enter", ele cria a seguinte estrutura:

import React from 'react'

const Checkbox = () => {
  return (
    <div>Checkbox</div>
  );
};

export default Checkbox

Na linha 3, podemos deletar o import do React, pois não vamos utilizá-lo por enquanto. Feito isso, temos o componente de Checkbox, que retorna apenas uma <div> com o nome "Checkbox".

A extensão utilizada anteriormente foi a "ES7+ React/Redux/React-Native snippets", que permite criar componentes, entre outras coisas do ecossistema React, em uma aplicação no Visual Studio Code.

Agora vamos criar o componente Checkbox. O Checkbox é um elemento <input> com o tipo checkbox. Então, dntro do return, na linha 5, vamos adicionar uma tag <label>, onde colocaremos o <input>.

Conforme mencionado, esse <input> tem um atributo type definido como checkbox. Abaixo desse <input>, na linha 7, vamos criar uma tag <span>, e entre chaves, receberemos uma legenda. Essa legenda dará um contexto para o <label>.

const Checkbox = () => {
  return (
    <label htmlFor="">
      <input type="checkbox" />
      <span>{legenda}</span>
    </label>
  );
};

Adicionando propriedades

Nesse momento, o Visual Studio Code reclama que não conhece essa legenda. Precisamos recebê-la via props. Então, na linha 3, entre os parênteses da arrow function, vamos escrever legenda também entre chaves, porque vamos desestruturar essas propriedades.

Vamos receber também outras propriedades, por exemplo: um id, um nome, uma prop que chamaremos de selecionado, e outra que vamos chamar de aoSelecionar.

Além disso, queremos receber todas as outras propriedades passadas para esse componente. Para isso, escrevemos três pontos seguidos de rest (...rest), ou seja, o restante das propriedades que esse componente receber.

const Checkbox = ({
  legenda,
  id,
  nome,
  selecionado,
  aoSelecionar,
  ...rest
}) => {
  return (
    <label htmlFor="">
      <input type="checkbox" />
      <span>{legenda}</span>
    </label>
  );
};

Feito isso, onde vamos passar essas propriedades? Como boa prática de HTML e CSS, precisamos linkar a <label> ao campo de <input>. Portanto, no atributo htmlFor da tag <label>, vamos passar entre chaves a propriedade id que recebemos, e no campo de <input>, teremos um atributo id que será o {id} que recebemos. Dessa forma, fazemos o link de um elemento em outro.

Outro atributo que esse novo componente vai ter será um name, que vamos receber da propriedade {nome} na tag <input>. Além disso, teremos um atributo chamado checked, para informar se o checkbox está checado ou não. Para isso, entre chaves, vamos receber a propriedade selecionado.

Haverá também o atributo onChange, um escutador de eventos do próprio React, onde iremos receber entre chaves a propriedade aoSelecionar.

Por fim, logo abaixo de onChange, vamos abrir chaves e, dentro delas, espalhar o ...rest. Assim, tudo que vier de propriedade, vamos espalhar no componente de Checkbox, especificamente em <input>.

const Checkbox = ({
  legenda,
  id,
  nome,
  selecionado,
  aoSelecionar,
  ...rest
}) => {
  return (
    <label htmlFor="{id}">
      <input
        type="checkbox"
        id={id}
        name={nome}
        checked={selecionado}
        onChange={aoSelecionar}
        {...rest}
      />
      <span>{legenda}</span>
    </label>
  );
};

Definindo os tipos das propriedades

Nessa etapa, o TypeScript irá reclamar que recebemos diversas propriedades, mas ele não conhece nenhuma delas, isto é, não sabe quais são os tipos. Para facilitar esse processo, já temos os tipos de todas essas propriedades que recebemos e vamos apenas colar na linha 3, acima do componente Checkbox.

interface CheckboxProps extends React.HTMLProps<HTMLInputElement> {
  legenda: string;
  id: string;
  nome: string;
  selecionado: boolean;
  aoSelecionar: () => void;
}

Com esse código, definimos uma interface chamada CheckboxProps, que estende do React os próprios tipos do elemento <input>, através do extends React.HTMLProps<HTMLInputElement>. Observe que passamos como um decorator o HTMLInputElement.

Isso nos permite que o ...rest recebido na linha 17 seja passado para o <input>, na linha 27. Como temos um elemento de <input>, todo rest que passarmos que tenha a ver com o elemento de input, automaticamente, o componente irá reconhecer e não haverá erro.

Portanto, estender de React.HTMLProps<>, do HTMLInputElement, especificamente, significa que todas as propriedades e atributos que o elemento de <input> pode receber, também poderão ser recebidos através da propriedade que definimos como rest na linha 17.

Além disso, temos os outros tipos: a legenda, o id e o nome são do tipo string; o selecionado é um boolean, isto é, verdadeiro ou falso; e o aoSelecionar é uma função do tipo que não retorna nada, portanto, () => void.

Finalizando o componente Checkbox

Na linha 18, vamos adicionar dois pontos (:) logo após as chaves dentro dos parênteses da arrow function, e passar CheckboxProps. Dessa forma, o Visual Studio Code e o TypeScript param de reclamar.

const Checkbox = ({
  legenda,
  id,
  nome,
  selecionado,
  aoSelecionar,
  ...rest
}: CheckboxProps) => {

Na label, também teremos o atributo className. Importamos um arquivo de estilos no início do arquivo, então vamos chamar className e passar a classe correta dele, que é checkbox_legenda.

<label htmlFor={id} className="checkbox_legenda">

Resultado do arquivo Checkbox.tsx:

import "./Checkbox.css";

interface CheckboxProps extends React.HTMLProps<HTMLInputElement> {
  legenda: string;
  id: string;
  nome: string;
  selecionado: boolean;
  aoSelecionar: () => void;
}

const Checkbox = ({
  legenda,
  id,
  nome,
  selecionado,
  aoSelecionar,
  ...rest
}: CheckboxProps) => {
  return (
    <label htmlFor={id} className="checkbox_legenda">
      <input
        type="checkbox"
        id={id}
        name={nome}
        checked={selecionado}
        onChange={aoSelecionar}
        {...rest}
      />
      <span>{legenda}</span>
    </label>
  );
};

export default Checkbox;

Feito isso, temos o componente Checkbox criado.

Falando sobre acessibilidade

Ainda não falamos nada sobre acessibilidade, apenas criamos o componente utilizando tags semânticas, como, por exemplo, <label> e <input>, e também passamos o atributo checked para a tag <input>.

Poderíamos passar uma aria-checked? Sim, mas o checked já é do próprio elemento de <input> e informa se o componente está selecionado ou não. Portanto, é um recurso próprio do <input> e, sendo assim, não precisaríamos utilizar o atributo aria-checked.

Utilizamos apenas HTML semântico e WAI-ARIA. Para quem não conhece, WAI-ARIA é um padrão com diretrizes de boas práticas, para darmos um comportamento semântico para elementos que não têm esse comportamento.

No caso, poderíamos passar uma aria-checked, mas como o elemento de <input> tem esse comportamento padrão de checado ou não, podemos passar apenas checked.

Conclusão

Criamos o componente Checkbox. Agora falta testá-lo na nossa página, mas faremos isso um pouco mais adiante, porque ainda queremos apresentar outro componente. Nos encontramos no próximo vídeo!

Caixas de seleção - Componente Radio Button

Quando desenvolvemos aplicações web e buscamos torná-las acessíveis, devemos ter atenção a quais são os vilões da acessibilidade.

Há elementos, principalmente de formulários, que são problemáticos e precisam receber atenção especial, a fim de proporcionar um contexto mais adequado para torná-los acessíveis. Um exemplo disso são os componentes de RadioButton.

Componente RadioButton

Com o projeto do Figma aberto no navegador, exibindo a página de produto, temos a descrição do produto, o valor e algumas opções. Essas opções são botões, isto é, os RadioButton, utilizados para selecionar, por exemplo, a cor do produto. No nosso caso, são três botões, então, provavelmente, eles estão dentro de um grupo de opções desse tipo de botão.

Consultando a documentação do WAI-ARIA

Para aprimorar o contexto desses componentes, podemos consultar a documentação do WAI-ARIA, onde encontramos diversos padrões para vários componentes, incluindo o padrão de grupo de rádio.

Nessa documentação, aprendemos, por exemplo, como deve ser a interação do teclado para esses elementos. Podemos navegar com as teclas "Tab" e "Shift + Tab", "Seta para cima", "Seta para baixo", "Seta para a esquerda", e "Seta para a direita", e marcar ou desmarcar esses elementos com a tecla "Barra de espaço". Recomendamos a leitura das outras informações disponíveis na documentação.

Criando o arquivo BotaoRadioGrupo.tsx

Nosso foco será criar o código desse componente. No Visual Studio Code, dentro da pasta "src > componentes", temos uma pasta chamada "BotaoRadio", que contém o arquivo BotaoRadio.css.

Nessa mesma pasta, vamos criar um arquivo chamado BotaoRadioGrupo.tsx. Feito isso, com o atalho rafce, para criar um reactArrowFunctionExportComponent, criamos toda a estrutura desse botão.

BotaoRadioGrupo.tsx:

import React from 'react'

const BotaoRadioGrupo = () => {
  return (
    <div>BotaoRadioGrupo</div>
  );
};

export default BotaoRadioGrupo

Construindo o componente BotaoRadioGrupo

Dentro do return, na linha 5, vamos deletar a <div> adicionada por padrão e utilizar algumas tags semânticas. Primeiramente, adicionaremos a tag <fieldset>. Dentro dela, passaremos uma tag <ul>, que será uma lista, e nessa lista, exibiremos um {children} que será recebido via props.

return (
  <fieldset>
    <ul>{children}</ul>
  </fieldset>
);

Acima de <ul>, haverá um grupo de opções que receberá uma legenda, que será usada para descrever o que é este grupo. Entretanto, essa legenda será opcional, então faremos uma verificação.

Se houver legenda, utilizamos a notação de retorno imediato do React, a &&, e renderizamos um elemento chamado <legend>, que combina muito bem com o <fieldset>.

O <fieldset> é uma tag semântica que serve para dar contexto para um grupo de opções, sendo comumente usada dentro de formulários.

A legenda se relaciona muito bem com a tag <fieldset>, porque também fornece um contexto de legenda. Quando uma pessoa com deficiência, que precisa de um leitor de tela, for navegar na nossa página, isso será lido de uma forma que facilite a interpretação do que se trata.

Sendo assim, vamos passar entre a tag <legend> a legenda entre chaves.

const BotaoRadioGrupo = () => {
  return (
    <fieldset>
      {legenda && <legend>{legenda}</legend>}
      <ul>{children}</ul>
    </fieldset>
  );
};

Adicionando propriedades

O próximo passo é receber como propriedade na linha 3, entre os parênteses da arrow function e entre chaves, o children, a legenda, e a ariaLabel, que servirá para dar um contexto melhor para o novo componente BotaoRadioGrupo.

Com o uso da propriedade ariaLabel, você perceberá como conseguimos combinar semântica HTML e padrão WAI-ARIA para fornecer mais contexto aos componentes da aplicação, tornando-os mais acessíveis.

Em seguida, na tag <fieldset> da linha 5, vamos adicionar algumas propriedades: primeiramente, a aria-label, recebendo entre chaves a ariaLabel que recebemos via props.

Também adicionaremos um tabIndex na linha 5, ainda na tag <fieldset>, e passaremos o valor de 0, pois queremos que esse elemento seja focável ao navegar com a tecla "Tab".

Esse componente recebe um className, o qual será radio__grupo--campos, mesma classe da tag <ul> na linha 7. Em <legend>, também teremos um className, que será radio__grupo--legenda.

const BotaoRadioGrupo = ({ children, legenda, ariaLabel }) => {
  return (
    <fieldset
      className="radio__grupo--campos"
      aria-label={ariaLabel}
      tabIndex={0}
    >
      {legenda && <legend className="radio__grupo--legenda">{legenda}</legend>}
      <ul className="radio__grupo--campos">{children}</ul>
    </fieldset>
  );
};

Criando a interface BotaoRadioGrupoProps

Agora temos o grupo de botões BotaoRadioGrupo. No entanto, o TypeScript reclama que não definimos os tipos dos elementos. Para resolver isso, criamos uma interface chamada BotaoRadioGrupoProps.

Essa interface possui: o children, do tipo React.ReactNode; a legenda?, que é opcional e do tipo string; e o ariaLabel, também do tipo string.

interface BotaoRadioGrupoProps {
  children: React.ReactNode;
  legenda?: string;
  ariaLabel: string;
}

Uma vez criada a interface, podemos chamá-la após as chaves e entre os parênteses de arrow function, adicionando : BotaoRadioGrupoProps.

Resultado do arquivo BotaoRadioGrupo.tsx:

import React from "react";

interface BotaoRadioGrupoProps {
  children: React.ReactNode;
  legenda?: string;
  ariaLabel: string;
}

const BotaoRadioGrupo = ({
  children,
  legenda,
  ariaLabel,
}: BotaoRadioGrupoProps) => {
  return (
    <fieldset
      className="radio__grupo--campos"
      aria-label={ariaLabel}
      tabIndex={0}
    >
      {legenda && <legend className="radio__grupo--legenda">{legenda}</legend>}
      <ul className="radio__grupo--campos">{children}</ul>
    </fieldset>
  );
};

export default BotaoRadioGrupo;

Conclusão

Assim, finalizamos o componente BotaoRadioGrupo, que servirá para encapsular os botões de rádio. Como você pode imaginar, eles virão através de um children e serão elementos de uma lista.

Discutiremos isso melhor em um próximo vídeo. Até lá!

Sobre o curso React: acessibilidade para desenvolver interfaces inclusivas

O curso React: acessibilidade para desenvolver interfaces inclusivas possui 140 minutos de vídeos, em um total de 55 atividades. Gostou? Conheça nossos outros cursos de React em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda React acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas