Arraste e solte componentes para usuários cegos? Você está brincando

O que une Trello, Gmail, Aviasales e Google Keep? Cada um deles possui componentes de arrastar e soltar que podem ser arrastados com o mouse. O uso desses componentes torna os sites realmente convenientes, porque na vida real costumamos usar esse padrão. É natural que movamos as coisas, por isso, na Web, queremos mover elementos da tela de um lugar para outro, como adesivos em um quadro negro ou ímãs em uma geladeira. Classificação de listas de tarefas, organização de painéis, download de arquivos - simplesmente não podemos imaginar todos esses eventos sem arrastar e soltar elementos na página.



Mas há uma nuance. Quando desenvolvemos esses componentes, achamos que nossos usuários veem fisicamente a tela e os elementos, podem pegá-los com o mouse e arrastá-los. Freqüentemente, mas esquecemos o segmento de usuários com problemas de visão. Criamos componentes que não podem ser usados ​​por um grande grupo de pessoas que simplesmente não os veem. Como tornar os componentes de arrastar e soltar acessíveis também?

Sergey Krieger é desenvolvedor front-end da SinnerSchrader. Além do desenvolvimento de front-end, ele está interessado ativamente no tópico de acessibilidade da Web e discutirá algumas maneiras de aumentá-lo. Sob o corte - uma história sobre a criação de componentes de arrastar e soltar para quem não vê a tela e usa outros dispositivos para interagir com o navegador.


Slider


Vamos começar com uma tela simples no site Aviasales da tela. Digite o ponto de partida, o ponto de chegada e a lista de voos para seleção é exibida na tela. Pode haver muitos voos, eles podem ser filtrados por preço, hora e outros parâmetros. Os controles deslizantes são usados ​​para filtrar os resultados no site da Aviasales. Eles ficam ótimos, são fáceis de usar.



Nossa tarefa é imaginar que somos os desenvolvedores deste site. Vamos tentar recriar esses controles deslizantes e ver como eles funcionam em diferentes casos.

Controle deslizante nativo


A primeira coisa a se pensar é se os elementos nativos podem ser usados ​​para nossa funcionalidade? Se houver essa oportunidade, seguimos por esse caminho, porque os elementos nativos economizarão muito tempo.

Vamos fazer um exemplo simples: o controle deslizante se move ao longo da trilha e o valor do controle deslizante muda. Mova o controle deslizante para a direita - a cor da tela muda de branco para rosa brilhante, se voltar - novamente para branco.



O controle deslizante funciona de maneira simples - o controle deslizante desliza ao longo da trilha e o controle deslizante retorna algum valor.

Ninguém usará esse controle deslizante na produção. Nenhum designer permitirá que ele use, porque ele parece fraco. Nós, como desenvolvedores, podemos resolver esse problema. Há várias propriedades CSS com prefixos para cada navegador, nas quais você pode estilizar elementos individuais do controle deslizante e refiná-lo.

: : -webkit-slider-runnable-track : : -webkit-sHder-thumb : : -moz-range-track : : -moz-range-thumb : : -ns-track :-ms-thumb : : -ms-fill-lower : : -ms-fill-upper 

Você pode usar as propriedades manualmente, mas isso não é uma tarefa trivial. As propriedades funcionam em diferentes navegadores, e os testes levarão muito tempo.

Mas há uma ferramenta especial que resolve o problema - o site de Daniel Stern . Você estiliza manualmente o controle deslizante, copia o código CSS e tudo funciona. O controle deslizante nativo agora é um elemento HTML de input com o range tipos, mas funciona como antes - movendo o controle deslizante.

Teste de controle deslizante


Para resolver o problema até o fim - testamos. Além disso, testaremos não apenas o controle deslizante, mas também outros elementos em três parâmetros.

  • O mouse Testar a operação do componente com o mouse é exatamente o que sempre fazemos.
  • Teclado Além do mouse, adaptamos o controle deslizante para pessoas com problemas de visão. Esses usuários não veem a tela e usam o teclado para interagir com o computador e o navegador
  • Leitor de tela - um dispositivo especial que lê as informações na tela.

Nota: daqui em diante é mais conveniente combinar testes de leitura e visualização em gravações de vídeo - isso é mais óbvio. Um segmento de vídeo com teste do controle deslizante começará no momento certo.


O mouse Nos agarramos ao controle deslizante, puxamos para a direita e esquerda. Se tudo mudar - ótimo.

Teclado Use a tecla Tab para ir para o controle deslizante e use as setas para movê-lo ao longo da trilha.

Leitor de tela . Aqui é mais complicado. Imagine que não vemos a tela - desligue a luz da tela e ligue o leitor de tela. Ele diz:

- O VoiceOver está ativado no Chrome .

Usando a tecla Tab, vá para o controle deslizante.

Zero. Aplicação de controle deslizante estilizado.

O leitor de tela exprime informações: valor, nome do controle deslizante e outras informações relacionadas, que também podem ser úteis. Começamos a mover o controle deslizante:

- Um, dois, três, quatro, cinco.

Se ouvirmos a contagem regressiva, tudo funcionará. Acenda a luz e verifique o resultado. Os testes terminaram.

Parece que não fizemos nada, mas simplesmente estilizamos o controle deslizante. Qual é o nosso trabalho sobre acessibilidade? O fato é que não houve trabalho - usamos o elemento nativo.

Se o seu aplicativo puder usar elementos nativos: controle deslizante, botões, caixas de seleção, fique à vontade para usá-los e economizar tempo. Esses elementos já suportam teclado e leitor de tela.

Controle deslizante personalizado


Suponha que o controle deslizante nativo não seja nossa opção. Vamos dar uma olhada no código Aviasales e ver que aqui não são os controles deslizantes que acabamos de testar.



Esta não é uma input com o range tipos, mas um conjunto de div estilizados conforme desejado pelo designer. Parece que não há diferença, tudo funciona.

Vamos verificar isso e complicar da mesma forma a tarefa criando manualmente um controle deslizante. A chave para mover o controle deslizante ao longo da pista é o posicionamento absoluto:

 position: absolute 

Posicionamos absolutamente o controle deslizante em relação à pista e, dependendo da sua posição, calculamos o valor do controle deslizante.

Para determinar o momento da captura de um elemento com o mouse, usamos o evento mousedown . Para rastrear o movimento do evento - mousemove e mouseup nos dirão que lançamos o controle deslizante. Para a tela de toque, também usaremos vários eventos: touchstart , touchmove e touchend .

Parece que tudo é simples. O controle deslizante terá a mesma aparência do exemplo anterior, mas no código não é um controle deslizante, mas um conjunto de div estilizados e o JavaScript será responsável por movê-lo. Ao trabalhar com um mouse, isso será imperceptível, mas há uma nuance no teclado. Para que o teclado possa capturar esse controle deslizante, oferecemos a propriedade de focar no atributo tabindex e usar JavaScript para rastrear o clique nas setas.

Teste do controle deslizante personalizado



Com um leitor de tela, será mais difícil. Desligue a luz, ligue o leitor de tela e tente alterar o valor. O leitor de tela exprime as ações e, se ele disser algo estranho, por exemplo, "grupos", pensamos.

"Grupos" é o que o leitor de tela expressa quando lê um div ou outro elemento que não possui nenhum papel semântico. Qualquer palavra que não se refira ao controle deslizante diz que a acessibilidade ainda não foi alcançada. Para disponibilizar o controle deslizante, usamos os atributos ARIA:

 <div class="thumb" tabindex="0"    role="slider"    aria-labl=""    aria-valuenow="5"    aria-valuemin="0"    aria-valuenax="10" ></div> 

Precisamos dizer ao leitor de tela que nosso elemento de estilo usual é um controle deslizante. Faremos isso usando role com o slider valor. Em seguida, atribua o nome ao controle deslizante usando o aria-labl . Definimos o valor atual do controle deslizante, o valor mínimo e máximo do controle deslizante. Usando esses cinco atributos do ARIA, animaremos o controle deslizante e faremos com que o leitor de tela diga o que precisamos.

Usando elementos de marcação, JavaScript e ARIA, disponibilizamos o controle deslizante personalizado para todos os usuários.

Classificação


Outra abordagem para implementar os componentes de arrastar e soltar é a classificação. Geralmente, os sites têm listas de itens que são bons para classificar.



Acima está uma captura de tela do site do Google Keep - é um serviço que permite criar listas de tarefas, folhas de tarefas. Uma folha de tarefas tem um nome, uma lista de elementos, a capacidade de marcar cada elemento, excluí-lo e adicionar um novo. Nossa tarefa é recriar essa funcionalidade.

É assim que o widget da lista de tarefas se parece.



Tem:

  • nome - lista de tarefas;
  • Elementos: passear com o cachorro, marcar uma consulta com o médico, que pode ser anotada ou excluída;
  • a capacidade de adicionar novos elementos - adicione uma tarefa.

Quando adicionamos um novo item, como "fazer o jantar", ele é colocado no final da lista. Este é um comportamento lógico - adicionamos o item por último. Mas vamos supor que essas listas tenham algum tipo de prioridade. Por exemplo, após um dia útil, o jantar é mais importante do que passear com um cachorro. Gostaríamos de passar para o início - os elementos prioritários devem estar no topo da lista. Como resolver este problema?

Como mover elementos, mesmo sem pensar em acessibilidade? Já sabemos de uma maneira - usando posicionamento absoluto. Outra maneira é adicionar o atributo draggable aos elementos. Se você adicionar esse atributo como true qualquer elemento, ele será arrastado. Você pode agarrá-lo com o mouse e arrastá-lo para outro local na tela.

Mas nem todos os elementos precisam do atributo draggable . Imagens e links não são necessários - eles são arrastados e soltos por padrão.

Somente se quisermos cancelar essa funcionalidade, definiremos draggable com valor false .

Transferência de dados


Existem dois elementos na tela. À esquerda, há uma imagem na qual o atributo draggable está implícito por padrão. À direita, há um elemento com uma linha tracejada. Nossa tarefa é arrastar a imagem para dentro do quadrado pontilhado, que chamei de “zona de soltar”.



Pegue a imagem e arraste-a para a zona de soltar. Esta funcionalidade familiar: podemos inserir a imagem na zona de arrasto, sair quando liberada - a imagem está dentro. Queremos a mesma funcionalidade em nossa lista de tarefas.



Mas antes que você veja como a lista de tarefas funciona com essa tecnologia, descobriremos o que acontece quando arrastamos um item de um lugar para outro. Uma lista de eventos acontece em cada um desses elementos.

Existem três eventos em um item arrastado.

Dragstart , que acontece uma vez quando iniciamos o processo de arrastar um elemento. Este é um evento importante, mais tarde descobriremos o porquê.

Um arrasto que ocorre regularmente a cada poucas centenas de milissegundos. Dependendo do navegador, o valor muda, mas o evento é frequente. Usando esse atributo, você pode rastrear a posição na tela do elemento que estamos arrastando.

Arrastar - dispara quando liberamos um item com o mouse.

Em um elemento que aceita outros elementos, quatro eventos são disparados.

Dragenter - alerta quando arrastamos um item dentro de outro item.

Dragover - diz quando começamos a movê-lo para dentro.

Dragleave - quando movemos um elemento além dos limites de outro elemento, sem soltar o mouse.

Drop é o evento mais importante que é acionado quando liberamos o mouse dentro do elemento receptor.

Todos esses 4 eventos são apenas pré-requisitos para o movimento do elemento - eles mesmos não fazem nada. Usando-os, você pode decidir o movimento de um elemento. Fazemos assim:

 draggable.addEventListener("dragstart", e => { e.dataTransfer.setData("text/plain", e.target.id); }); dropZone.addEventListener("drop", e => { const id = e.dataTransfer.getData("text/plain"); const el = document.getElementById(id); }); 

Podemos adicionar dados manualmente ao evento que é acionado no início no elemento que estamos arrastando. Usando o método dataTransfer.setData , adicionamos o seletor do item que estamos arrastando. No nosso caso, isso é id .

No final, quando o evento Drop é acionado no elemento de recebimento, obtemos esses dados usando o método dataTransfer.getData . Acontece que teremos o id elemento que queremos mover. Em seguida, usando JavaScript comum, selecione esse elemento na página e mova-o para qualquer lugar. Nós nos movemos à mão. Para tornar isso possível, usamos eventos no elemento arrastar e soltar.

Podemos arrastar qualquer elemento sobre qualquer outro elemento. Basta arrastar o elemento pela página e apontar para outras pessoas. Mover não significa que um elemento deve aceitar outro se não foi planejado. Portanto, os navegadores funcionam desta maneira: por padrão, nenhum elemento pode aceitar outros.

Se queremos ensinar o elemento a aceitar outras pessoas, precisamos cancelar esse valor usando o método e.preventDefault() no dragenter e dragover , que é dropZone elemento dropZone .

 dropZone.addEventListener("dragenter", e => { e.preventDefault(); }); dropZone.addEventListener("dragover«, e => { e.preventDefault(); }); 

Eu testei essa combinação em diferentes navegadores. Por exemplo, apenas o dragenter funciona no Chrome, portanto, use o dragenter e o dragover para uma solução entre navegadores.

Vamos ver como isso funciona na lista de tarefas.



Nossa tarefa é arrastar o último item da lista de tarefas familiar para a primeira posição. Passe o mouse sobre um elemento e um elemento com 6 pontos verticais aparece à esquerda. No mundo UX, isso significa que você pode arrastá-lo.



Passamos o mouse sobre ele e, se ele mudar, esse é um sinal de que o elemento está pronto para se mover. Puxe o mouse e um indicador rosa aparecerá, indicando onde você pode mover o item. O restante da técnica é colocar o objeto na posição desejada.



Agora vamos ensinar o teclado e o leitor de tela a processar corretamente o que acabamos de fazer.

Teclado


Com o teclado, tudo não é tão complicado. Com o teclado, usamos o mesmo padrão do mouse: encontramos o elemento que queremos mover, selecionamos, movemos e depois liberamos, e ele se encaixa no lugar.

Pressione Tab e um ícone familiar de 6 pontos aparece à esquerda do primeiro elemento, o que indica que você pode arrastar e soltar. Por padrão, ele está oculto e sua aparência significa que tomou o foco. Este é um sinal de que você pode interagir com esse elemento.

Introduzimos o primeiro elemento "cozinhar o jantar" no "modo de seleção" pressionando "Enter". Este item está atualmente recebendo opções adicionais. As setas para cima e para baixo podem movê-lo para outras posições. Pressione a seta para baixo, o item move uma posição, mais uma vez para outra. Então, movemos manualmente o componente. Esse não é o padrão no navegador - nós o escrevemos manualmente em JavaScript.



Quando queremos remover a seleção do elemento, pressione "Esc" ou qualquer outra tecla - o elemento perde a seleção e permanece no lugar certo.

Leitor de tela


Tudo está claro com o teclado. Quase resolvemos o problema. Resta ensinar ao leitor de tela a pronunciar ações. Tudo o que é necessário é adicionar instruções para que o leitor de tela saiba o que está acontecendo: onde está e o que fazer.

Para controlar o que o leitor de tela diz, usaremos a tecnologia da região Live. Este é um conjunto de atributos que podem ser adicionados aos elementos. Dependendo dos atributos, o leitor de tela pronuncia frases diferentes.

 <div class="live-region visually-hidden"    aria-live="polite"    role="status" ></div> 


 const liveRegion = document.querySelector(".live-region«); liveRegion.textContent = ' '; 

aria-live o atributo aria-live com um valor polite div vazia normal e a role com um valor de status . Para um leitor de tela, este é um sinal para ouvir um elemento. Quando você quiser que o leitor de tela diga alguma coisa, atualize o conteúdo usando JavaScript, e o leitor de tela dirá esse conteúdo.

Vamos ver como isso funciona.


Nossa tarefa é mover o primeiro elemento para a última posição. Desligue a luz da tela, ligue o leitor de tela.

- O VoiceOver está ativado no Chrome.

Começamos a mover o item. Primeiro, procure nosso widget - mova-se pelos cabeçalhos. Vozes do leitor de tela:

- Título de nível dois. Lista de tarefas.

Encontrei. Continuamos a clicar na tecla Tab.

- Lista de objetos 3. Pressione a tecla “Enter” para selecionar o elemento “Ande com o cachorro”. Grupos.

Primeiro, o leitor de tela pronuncia o número de elementos na lista, para que os usuários entendam quantos elementos estão na lista. Em seguida, ele pronuncia uma instrução - o que fazer para selecionar um item: "Pressione a tecla Enter e o nome deste componente. Ficou claro o que fazer - pressione a tecla Enter.

- O elemento "Passear com o cachorro" está selecionado. Use as teclas Para cima e Para baixo para mover. Use a tecla Esc para desmarcar.

Foi sobre estas instruções que falei: quando você seleciona um elemento, o leitor de tela fornece as instruções que criamos. Atualizamos o leitor de tela e pronuncia o texto que colocamos no elemento Região ao vivo. Com as instruções, fica claro o que fazer - use as teclas Para cima / Para baixo e Esc para desmarcar. Mover para baixo uma posição.

- O elemento "Passear com o cachorro" é movido para a posição 2.

Mais uma vez

- O elemento "Passear com o cachorro" é movido para a posição 3.

O item está no final da lista. Acenda a luz e verifique se o elemento está realmente na última posição.

Pressione "Esc" para desmarcar.

- O item "Dê um passeio com um cachorro" foi desmarcado.

Com a ajuda dos atributos imaginação, marcação, JavaScript e ARIA, disponibilizamos um widget difícil para usuários com problemas de visão.

Movendo


Vejamos como mover elementos pela página usando o Trello como exemplo. Este é um rastreador de tarefas com colunas que indicam o status das tarefas. Arrastar e soltar tarefas de uma coluna para outra corresponde a uma alteração no status da tarefa.



Simule uma versão simplificada do Trello para descobrir como disponibilizar esse componente. Na minha versão, existem três colunas: "Eu vou fazer", "Eu faço", "Concluído".



As tarefas podem ser arrastadas de um lugar para outro: pegue o componente com o mouse, arraste-o para a próxima coluna, solte-o - ele permanece lá.

Teclado


Tudo é simples com o mouse; estamos familiarizados com o atributo draggable com o valor true do exemplo anterior. Com o teclado, foi possível fazer a mesma opção - mover a tarefa de coluna em coluna com setas. Porém, se as colunas forem 5 ou 8, a mudança da primeira para a última levará 5 ou 8 cliques na tecla Direita 5 ou 8 vezes, o que é inconveniente e dificulta o trabalho com o componente.

Faremos o contrário. Pressione a tecla Tab, o foco se move para o primeiro elemento. Pressione a tecla novamente e um novo elemento aparecerá oculto até que o foco se movesse para ele.



Três pontos verticais significam que o item terá um menu. O ícone pode ser diferente. O comportamento padrão do navegador ao trabalhar com o elemento select é clicar em "Espaço", após o qual um menu é exibido.

Resolveremos o problema usando JavaScript, mas daremos aos usuários a oportunidade de escolher qual coluna eles desejam mover esta ou aquela tarefa.



Passamos para a última coluna, pressionamos “Enter” e tudo funcionou - o elemento foi para onde queríamos.

Leitor de tela


Adicione instruções para o leitor de tela. O uso do elemento de select regular oferece uma grande vantagem, pois está disponível por padrão. Vamos ver o que podemos fazer.


Desligue a luz da tela, ligue o leitor de tela.

- O VoiceOver está ativado no Chrome.

Passamos para o primeiro elemento. O leitor de tela diz quantos objetos estão na lista. Usamos a elementos semânticos e o nome do elemento. Pressione Tab.

- "Make": selecione o botão pop-up recolhido do botão "Play Soccer", grupos.

O leitor de tela pode pronunciar palavras estranhas. Ele chama o nome da coluna "Make" e "pop-up minimizado" para o leitor de tela significa que usaremos o menu - para o usuário do leitor de tela isso ficará claro. "Minimizado", "pop-up" e "botão" serão pronunciados diferentemente em leitores de tela diferentes, mas não precisamos nos preocupar muito com isso, porque os usuários do leitor de tela estão familiarizados com esse comportamento.

Nossa tarefa é selecionar a coluna desejada da lista.

- Não é zero, faça. Selecione o botão pop-up expandido da coluna. Sua posição atual na tela ... "Fazendo". "Concluído" ... O item "Jogar futebol" foi movido para a coluna "Concluído".

Este é o texto que adicionamos manualmente para informar aos usuários que o fizemos. É assim que nosso quadro de tarefas funciona.

Carregar arquivos


A funcionalidade de upload de arquivo também é encontrada em sites, por exemplo, para anexar arquivos a um email. Portanto, no meu exemplo, o email é Gmail.



Há um elemento com uma linha tracejada na tela. É aqui que vamos arrastar nossos arquivos.



Para fazer isso, abra o explorer onde os arquivos estão localizados e arraste o arquivo com o mouse para a zona tracejada. Após arrastar e soltar, o item muda de estado, libera o arquivo, o download é iniciado. No final do download, notificaremos o usuário de que tudo foi baixado com sucesso.

Teclado


Com o teclado, tudo é resolvido de forma simples. Há um elemento de input semântica do tipo file . Se você o usar, quando clicar nesse item, a caixa de diálogo Explorer será aberta automaticamente, onde você poderá selecionar os arquivos no sistema operacional. Os estilos de janela podem ser definidos de maneira absolutamente qualquer, dependendo dos desejos do seu designer.



Clique no item, uma caixa de diálogo é aberta. Como usamos o elemento de input nativo, você também pode ir para esse elemento com a tecla Tab, pressionar a barra de espaço e uma caixa de diálogo será aberta. Os elementos são selecionados com a tecla Enter e tudo acontece da mesma maneira.

Tudo funciona com o mouse e o teclado. Para o leitor de tela, você pode fazer algo que, por padrão, não é fornecido por elementos nativos.

Leitor de tela


O elemento "select" funcionará e ainda podemos abrir uma caixa de diálogo com o SO. , screen reader .


screen reader. , .

— button application.

screen reader.

— button. … image.png. 31 … 0%… 16% … 73% … 100% . image.png .

? , , . , screen reader , . , , .

, screen reader . — 10%, 20%...100%. , , , .

Live region, . screen reader, , ARIA Live, screen reader . .

Sumário


. — . , , screen reader. , , .

HTML + JavaScript + ARIA . Drag-&-Drop , JavaScript ARIA. , .

« » . , « »: , , , , .

. : , , .


, W3.org — . .

, , inclusive-components.design . . , , , , , .

. , , « ». — . .

. , — Medium . , . , . , , . . , .

. FrontendConf ++ . FrontendConf 2019 Leonie Watson — , W3C W3C -. Leonie screen reader. , , , , .

FrontendConf , . , .

Source: https://habr.com/ru/post/pt468541/


All Articles