Como tornamos o Yandex Cloud mais acessível com o sistema de design Gravity UI

Olá, meu nome é Vova Timofeev, sou gerente de projetos técnicos no Yandex Cloud. Neste artigo, vou compartilhar como tornamos o site da plataforma de nuvem mais acessível, quantas iterações fizemos e qual foi o papel do Gravity UI nisso.

A base da acessibilidade de todos os serviços é o quão bem eles suportam o uso de leitores de tela (Screen reader). Por meio desses programas, usuários com limitações percebem a interface e interagem com ela.

Sites não são exceção. E nós precisávamos descobrir o quão acessível o Yandex Cloud é para todos os usuários.

No Yandex, por acessibilidade entendemos que nossos serviços devem poder ser usados com conforto por todos, independentemente de limitações físicas temporárias ou permanentes. Por exemplo, hoje 16 serviços do Yandex já são adaptados para usuários cegos: Lavka, Go, Busca, Navegador, Mail e outros. No trabalho de acessibilidade de cada serviço, contamos com a equipe de testes não visuais — e no caso sobre o qual vou falar neste artigo, também não foi diferente: sem a ajuda deles, não teria sido possível.

Spoiler: durante os testes, encontramos alguns pontos discutíveis no uso de leitores de tela, que viraram tarefas reais.

Mas vamos por partes.

Tudo começou com o Gravity UI

Gravity UI é uma design system e biblioteca de componentes na qual funciona o site do Yandex Cloud e dezenas de outros produtos da nuvem. Ela está em open source e disponível para todos (ficamos felizes em ver que, nos últimos seis meses, a atividade no chat da comunidade cresceu de forma perceptível).

O que temos:

  • um conjunto de componentes React básicos;
  • uma biblioteca-construtor para landing pages;
  • guias detalhados de designers sobre como usar os componentes;
  • biblioteca no Figma;
  • um conjunto de quase 600 ícones prontos;
  • ChartKit — pacote para visualização de dados;
  • Yagr — renderização de gráficos de alta performance baseada em uPlot;
  • i18n — pacote para localização da interface;
  • outras bibliotecas úteis.

Em março de 2024, saiu uma atualização da biblioteca-chave — a versão 6 do UIKit. Nela, o componente List foi atualizado, surgiu suporte ao parâmetro RTL em todos os componentes e um conjunto de melhorias de a11y que aumentam a acessibilidade.

O que há de novo na versão 6 do UIKit
  1. Componente List 2.0. No UIKit havia originalmente o List, mas queríamos ajustar algumas coisas nele. Ao coletar solicitações, montamos uma lista:

    • suporte a diferentes tamanhos e larguras;
    • ícone no item da lista, quantidade e posição diferentes de ícones;
    • suporte a estados;
    • conteúdo diferente nos itens da lista (uma linha, várias linhas ou lista de usuários);
    • suporte a diferentes tipos de separadores e agrupamentos.

    Essas são mudanças significativas, então criamos o List 2.0. Por enquanto ele sai na versão prestable, mas recomendamos que os usuários migrem para ele e tragam feedback.

  2. RTL. Se seus aplicativos ou sites precisam ser exibidos em hebraico, árabe e outras línguas com direção de escrita da direita para a esquerda, é necessário suporte aos padrões RTL. Ao mesmo tempo, em RTL:

    • uma palavra em alfabeto latino inserida é escrita da esquerda para a direita;
    • números são escritos da esquerda para a direita;
    • pontuação em árabe também é escrita da esquerda para a direita etc.

    Em todos os componentes, adicionamos suporte ao parâmetro RTL. Para ter um exemplo completo à mão, fizemos uma página de promoção em árabe. Você pode ver como isso foi implementado no código-fonte do landing. Também há exemplos no storybook.

  3. Acessibilidade (a11y):

    • adicionamos ao projeto o plugin eslint;
    • adicionamos suporte a teclado para o estado clickable e closable do componente Persona;
    • desativamos onClick em 15 componentes não interativos;
    • adicionamos suporte a teclado no componente SelectionTable.

Como chegamos às melhorias de a11y

Nisso ajudou a equipe de testes não visuais e seu líder Anatoly Popko. Na reunião, Anatoly testou passo a passo o sandbox e o site do Gravity UI para entender quais problemas de acessibilidade existiam naquele momento.

Verificamos a acessibilidade dos componentes, navegando pelo site com o teclado e com comandos especiais dos leitores de tela.

Visualmente, era assim:

Full screen image

Após a reunião, a equipe ganhou tarefas de trabalho e no GitHub surgiram três novas issues sobre componentes básicos.

Mais detalhes sobre elas:

  • No menu suspenso, o segundo nível de itens não abre pelo teclado — apenas via clique do mouse.
Full screen image
  • Não fica claro qual item da lista com marcadores em markdown está selecionado no componente Select.

  • Botões sem rótulos textuais, indicados apenas graficamente, são anunciados apenas como “botão” ou “radio button”. Esse bug aparece apenas no landing; o componente em si suporta aria‑label, mas nós não o utilizamos.

Full screen image

Como resultado, entendemos que, já que não encontramos dezenas de observações, a acessibilidade da biblioteca já está em um nível razoavelmente bom. Testar componentes fora de um contexto real é muito difícil, então decidimos começar a checar a acessibilidade de um produto pronto. Assim conseguimos encontrar melhorias adicionais de a11y.

Acessibilidade do Yandex Cloud

Inspirados pela atualização do Gravity UI, decidimos testar a acessibilidade dos nossos serviços: começar pelo site do Yandex Cloud e depois levar essa experiência para outras interfaces.

Existe uma série de padrões que, quando seguidos, ajudam a alcançar acessibilidade. Mas, para testar de forma confiável as interfaces do Yandex Cloud e entender melhor o quão conveniente nosso site é para todos, realizamos uma auditoria.

Auditoria de acessibilidade

Voltamos a procurar os colegas da equipe de testes não visuais e o Anatoly para, juntos, testar o site, registrar problemas e levá-los para correção. No total, foram duas iterações com uma diferença de quase um mês — teste e reteste.

Durante o teste, registramos um conjunto inteiro de ajustes que precisariam ser implementados.

Na página principal

  • O controle de busca precisava ser redesenhado. Na nossa interface, o componente de busca é implementado como uma área de busca com um ícone de lupa. Ao clicar neles, abre-se um campo para digitar a consulta. Na implementação anterior, para o leitor de tela eram elementos independentes, o que confundia usuários cegos.

    image

  • Na seleção de idioma, usamos o atributo de estado “recolhido”, embora na prática fosse um botão de seleção e não um menu suspenso. Faltava o rótulo “idioma” e faltava um espaço na transição “idioma — região”.

  • No menu da conta, o foco não ficava preso: ao ativar, o usuário saía dos itens do menu.

  • A tag main na página principal era duplicada, então precisaríamos remover uma delas.

  • Seção com exemplos: era necessário usar uma aba em vez de um botão.

Full screen image
  • No card do exemplo, o texto foi colocado em aria‑describedby, por isso o leitor de tela lia o texto apenas uma vez, o que é inconveniente ao analisar informações importantes. Quando investigamos o bug, entendemos que valia fazer um refatoramento mais amplo do componente Card e abrimos uma issue em que é possível ver detalhes das mudanças e participar da discussão.
  • Problema de foco: ao expandir o nível superior do menu, era necessário mover o foco para o submenu.
  • Era necessário remover o TabIndex do nível superior do menu. O comportamento atual levava à leitura duplicada de todos os itens do menu.
  • Era preciso prender o foco do teclado na navegação quando ela estivesse expandida. Caso contrário, era possível “escapar” do menu para a página e depois não conseguir voltar.
  • O Yandex Cloud estava envolto por uma lista. Os títulos das listas de links no footer estavam dentro de um item de lista, então o NVDA os identificava como parte da lista e lia a mesma lista duas vezes para o usuário.
  • Faltavam rótulos para links da AppStore e do Google Play. No momento do teste, eram lidos fragmentos do URL, então o usuário não entendia nada.

Seção “Blog”

  • Os botões “Todos os temas” e “Todos os serviços” não estavam associados ao botão. Os botões dos selects não anunciavam o conteúdo.
  • Era necessário suporte de acessibilidade nas listas: ao abrir o menu suspenso, o foco do leitor de tela deve ir para os itens dessa lista. Além disso, deve haver navegação simplificada entre eles usando as setas comuns — sem combinações de teclas.

Artigos do blog

  • Faltava o elemento “Você está aqui” no breadcrumb.
  • Era preciso prender o foco no diálogo.
  • O contador de favoritos não tinha nome. O contador era um botão com um ícone e um número. Leitores de tela liam apenas o número — sem o ícone, não dava para entender o que o botão faz.

Reunimos todas as tarefas em um épico e começamos o trabalho. Para parte das tarefas, foram criadas issues no GitHub.

Vou falar com mais detalhes sobre os casos mais interessantes.

Componente Select

Full screen image

Durante os testes, descobrimos que, na navegação por teclado, os nomes dos itens da lista não eram anunciados pelo leitor de tela. Em parte, conseguimos corrigir o problema com o atributo aria‑activedescendant, mas não completamente.

Quais problemas permaneceram

  • No Safari, esse método não funciona e ainda não está claro como resolver.

  • O filtro de busca nem sempre é suportado (na verdade, sempre — só que o suporte não foi implementado). Normalmente, aria‑activedescendant é aplicado ao elemento principal do dropdown e aponta para o item selecionado na lista. Agora ele é aplicado ao botão que abre o dropdown. Ao pressionar as setas para cima/baixo, mudamos o valor de aria‑activedescendant no botão para o item anterior ou seguinte da lista. Assim, o leitor de tela consegue ler, a partir do botão selecionado, qual item está selecionado no momento.

    O problema do filtro de busca é que o campo de entrada do filtro não tem o atributo aria‑activedescendant. Se a pessoa focar no campo de entrada do filtro e quiser digitar, o leitor de tela não consegue ler a partir dele qual item da lista está ativo, e a navegação com as setas deixa de funcionar.

  • As opções selecionadas não estão marcadas; é preciso adicionar um atributo nelas, por exemplo aria‑selected.

A issue com os problemas atuais pode ser vista aqui.

Full screen image

Breadcrumbs é um elemento de navegação que mostra o caminho do usuário no site. No nosso caso, o leitor de tela lia o caminho inteiro e era impossível entender em qual parte do site a pessoa estava. Além disso, o componente inteiro era apresentado simplesmente como um conjunto de links.

Decidimos nos afastar dos padrões e resolver essa tarefa de forma simples e otimizada — adicionando para o leitor de tela o rótulo “Você está aqui”. No fim, combinamos a abordagem padrão com o rótulo.

Durante o trabalho, descobrimos: para que esse rótulo fosse lido, era preciso colocá-lo em um elemento que os leitores de tela não ignorassem. Foi mais fácil colocar o rótulo em uma estrutura convencional do que inventar um jeito de evitá-la. Mesmo assim, o rótulo continua útil: ele ajuda o usuário a entender mais rapidamente que o que ele está ouvindo são breadcrumbs.

Imagens sem legenda

Algumas imagens no site estavam sem legendas, e o leitor de tela as lia como “Imagem”. Essa informação não é útil para o usuário e não ajuda a compreender a interface, então decidimos ocultar imagens sem legendas do leitor de tela.

Ordem do texto em blocos

Full screen image

Em vários lugares do nosso site, a informação é apresentada como um bloco único — por exemplo, um card de evento ou um card de artigo no blog.

Percebemos que leitores de tela leem a informação em uma ordem que não é seguida por usuários videntes. No card do evento, o leitor de tela lia os dados assim: status de inscrição, horário, local e só depois o título e a descrição do evento.

Em geral, o usuário não segue um caminho linear: ele olha para o título, depois para o subtítulo e para a imagem. O problema é que o leitor de tela lê os elementos na ordem em que estão posicionados na árvore DOM da página. Para corrigir a ordem, nós tivemos que remontar o DOM.

Full screen image

Ficamos surpresos, mas em algumas combinações de “sistema operacional — navegador” isso não funcionou. Por exemplo, no Mozilla Firefox no macOS, o problema permaneceu apesar da mudança da ordem no DOM. Vamos torcer para que os desenvolvedores do Firefox corrijam esse comportamento nas versões mais novas do navegador.

Janelas modais

Full screen image

Quando um usuário vidente abre uma janela pop-up na interface, o olhar dele vai para o que está dentro dessa janela. No entanto, ele ainda tem acesso ao conteúdo de todo o site e, se necessário, pode voltar a atenção para ele.

Quando o site é usado com leitor de tela, a situação muda para o usuário. Se a janela pop-up não for modal, ela não terá limites. Como resultado, a navegação pelo site ficará mais difícil: a pessoa pode sair do pop-up por engano, usando a navegação por elementos.

Há um padrão para trabalhar com janelas modais e, se segui-lo, não é obrigatório tornar todos os pop-ups modais.

Mas durante os testes, chegamos à conclusão de que tornar as janelas pop-up modais é uma boa prática que simplifica o uso do site com leitores de tela.

Decidimos tornar todas as janelas pop-up modais. Ao mesmo tempo, deixamos para o usuário a possibilidade de configurar um cenário alternativo de trabalho com essas janelas.

Você pode configurar esse cenário atribuindo role="dialog", aria-modal="true". Na combinação VoiceOver + Firefox, essa solução não é suportada: há detalhes em uma issue fechada.

Diplodoc

Pegando carona na nossa atividade, os desenvolvedores da plataforma de criação de documentação técnica Diplodoc fizeram uma série de melhorias de a11y no produto deles:

  • Verificaram todos os elementos adicionais de sintaxe do YFM (Yandex Flavored Markdown) e reescreveram para que fossem visíveis para leitores de tela.
  • Melhoraram o fluxo de trabalho com a documentação via teclado: corrigiram a ordem de seleção de elementos e adicionaram a possibilidade de seleção para todos os elementos interativos.
  • Adicionaram rótulos e indicações corretas para elementos da interface, o que vai simplificar significativamente o uso do serviço para usuários com leitores de tela.

Como usamos o Diplodoc para exibir nossa documentação, essas melhorias também aumentaram a acessibilidade da documentação no site do Yandex Cloud.

Resultados e planos

Demos os primeiros passos para melhorar a acessibilidade das interfaces do Yandex Cloud para todos os usuários. Ainda precisamos levar essa experiência para outras interfaces do serviço e corrigir os problemas que já conhecemos.

O Gravity UI facilitou nosso trabalho com acessibilidade, e continuamos a trabalhar nas issues abertas com a tag a11y. No momento em que este artigo foi escrito, temos 14 issues abertas e 24 fechadas; você pode vê-las aqui.

Full screen image

Aguardamos seus PRs e comentários sobre acessibilidade e sobre o funcionamento dos serviços, assim como exemplos de uso do Gravity UI nos seus sites.

image

Владимир Тимофеев
Gerente de projetos técnicos do Yandex Cloud

Como tornamos o Yandex Cloud mais acessível com o sistema de design Gravity UI

Sign in to save this post