Atalho de teclado na web: como mostrar, não brigar com o navegador e não sumir
Leve os atalhos do sistema desktop para a web sem roubar teclas do navegador e do leitor de tela, com lista visível, opção de desligar e o clique sempre disponível.
O sistema de pedidos da distribuidora rodava em VB havia quinze anos. F2 abria um pedido novo, F3 buscava cliente, F9 fechava a venda. As atendentes digitavam um pedido em quarenta segundos sem tocar no mouse. Aí o sistema virou web, os atalhos foram reimplementados "do mesmo jeito" e, no primeiro dia, F3 abriu a busca do navegador, F5 recarregou a página com o pedido pela metade e ninguém sabia que F2 ainda funcionava.
A resposta curta: atalho que não está escrito na tela não existe para quem chegou depois, e atalho na web divide o teclado com o navegador, o sistema operacional e o leitor de tela. Mostre o atalho ao lado da ação, use combinações que não colidem com as do navegador, não dispare atalhos de uma letra enquanto a pessoa digita, permita desligá-los e mantenha toda ação acessível por clique e por foco.
Por que o atalho do desktop não sobrevive à web
No programa desktop, a janela é dona do teclado. No navegador, o evento passa por camadas antes de chegar à sua página, e algumas nunca chegam:
- O navegador reserva teclas. F5 recarrega, F11 alterna a tela cheia, F12 abre as ferramentas de desenvolvedor, F3 e Ctrl+F buscam na página. Combinações como Ctrl+T, Ctrl+W e Ctrl+N, que abrem e fecham abas e janelas, em geral nem chegam à página nos navegadores principais.
- O leitor de tela intercepta antes. No modo de navegação do NVDA e do JAWS, letras soltas são comandos do leitor (H pula para o próximo título, por exemplo). Quem usa leitor depende dessas teclas para se mover na página.
- O sistema operacional também. Combinações com a tecla Windows ou com Command no macOS costumam ser do sistema.
- Teclado não é igual em todo lugar. No ABNT2, algumas teclas de símbolo ficam em posições diferentes do layout americano, e notebooks exigem Fn para chegar às teclas de função.
Atalhos de uma única letra, sem modificador, são os mais perigosos: alguém usando comando de voz que dita uma palavra dispara meia dúzia de ações. Por isso as diretrizes de acessibilidade WCAG têm um critério específico (2.1.4, atalhos de caractere): se existir atalho de uma tecla só, a pessoa precisa poder desligá-lo, remapeá-lo, ou ele só vale quando o componente está em foco.
Como desenhar atalhos que as pessoas descobrem e usam
- Liste as ações que merecem atalho. Só as frequentes: na distribuidora, novo pedido, buscar cliente, adicionar item e fechar venda. Dez atalhos que ninguém lembra valem menos que quatro que todo mundo usa.
- Escolha teclas que o navegador entrega. F2 costuma estar livre; F3 e F5 não. Combinações com Alt+Shift ou sequências como "g" seguido de "p" (estilo de vários sistemas web conhecidos) colidem menos. Teste cada uma no Chrome, no Edge e no Firefox.
- Mostre o atalho perto da ação. No botão, na dica de foco ou no menu: "Novo pedido (F2)". Declare também com o atributo
aria-keyshortcuts, que informa a tecnologia assistiva. - Ofereça uma lista com a tecla
?. Um painel com todos os atalhos, aberto por?e por um link visível "Atalhos de teclado" no rodapé ou no menu de ajuda. - Ignore atalhos quando a pessoa digita. Se o foco está num campo de texto, a letra é texto. Só teclas de função ou combinações com modificador valem ali.
- Deixe desligar. Uma opção nas preferências que desativa atalhos de tecla única, guardada por usuário.
- Mantenha o caminho sem atalho. Toda ação com atalho continua sendo um botão ou link que funciona com clique, toque, Tab e Enter.
Exemplo: os atalhos da distribuidora em JavaScript
O código abaixo implementa F2 (novo pedido), Alt+Shift+B (buscar cliente), ? (lista de atalhos) e respeita campos de texto e a preferência de desligar.
// atalhos.js
const atalhos = [
{ combinacao: 'F2', acao: 'novo-pedido', tecla: 'F2', alt: false, shift: false, unica: false },
{ combinacao: 'Alt+Shift+B', acao: 'buscar-cliente', tecla: 'b', alt: true, shift: true, unica: false },
{ combinacao: '?', acao: 'ver-atalhos', tecla: '?', alt: false, shift: null, unica: true }
];
function estaDigitando(alvo) {
if (!alvo) return false;
const tag = alvo.tagName;
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || alvo.isContentEditable;
}
function atalhosUnicosLigados() {
return localStorage.getItem('atalhos-unicos') !== 'desligados';
}
document.addEventListener('keydown', (e) => {
if (e.defaultPrevented || e.isComposing || e.ctrlKey || e.metaKey) return;
const encontrado = atalhos.find((a) =>
e.key.toLowerCase() === a.tecla.toLowerCase() &&
e.altKey === a.alt &&
(a.shift === null || e.shiftKey === a.shift)
);
if (!encontrado) return;
if (encontrado.unica && (estaDigitando(e.target) || !atalhosUnicosLigados())) return;
const botao = document.querySelector('[data-acao="' + encontrado.acao + '"]');
if (!botao || botao.disabled) return;
e.preventDefault();
botao.click(); // o atalho só aciona o mesmo botão que o mouse usaria
});
Dois detalhes importam. Primeiro, o atalho chama botao.click(): a lógica mora no botão, e o atalho é só outro caminho até ele. Se o botão está desabilitado, o atalho também está. Segundo, preventDefault só roda quando o atalho foi reconhecido; o resto do teclado continua do navegador. Em alguns sistemas, Alt+Shift alterna o idioma do teclado; se a sua equipe usa isso, troque a combinação.
No HTML, o atalho aparece escrito e declarado:
<button type="button" data-acao="novo-pedido" aria-keyshortcuts="F2">
Novo pedido <kbd>F2</kbd>
</button>
<button type="button" data-acao="buscar-cliente" aria-keyshortcuts="Alt+Shift+B">
Buscar cliente <kbd>Alt+Shift+B</kbd>
</button>
<button type="button" data-acao="ver-atalhos">
Atalhos de teclado
</button>
E o accesskey?
O atributo accesskey existe, mas a combinação que o ativa muda por navegador e sistema (Alt, Alt+Shift, Control+Option), costuma colidir com menus do navegador e não aparece para ninguém. Para um sistema interno com muitas ações, um tratador próprio como o de cima, com lista visível, é mais previsível.
Migrando atalhos de um sistema antigo
Na distribuidora, a solução que funcionou foi um mapa de transição: F2 e F9 continuaram (o navegador não usa), F3 virou Alt+Shift+B, e o painel de atalhos mostrou a coluna "no sistema antigo" por três meses. As atendentes leram uma vez e voltaram aos quarenta segundos por pedido. Sem o painel, cada uma descobriria sozinha, por tentativa e erro, que F3 tinha mudado.
O mesmo cuidado com teclado vale para outras interações: veja por que evento de mouse não cobre o teclado e dica flutuante que precisa aparecer no foco.
Erros comuns
- Atalho sem nenhuma indicação na tela. Só quem programou conhece; pessoa nova pergunta no chat ou nunca usa.
- Capturar F5 ou Ctrl+F. Quem quer recarregar ou buscar na página perde o comportamento que espera e passa a desconfiar do sistema.
- Atalho de letra única ativo dentro de campo de texto. A atendente digita o nome "Bruno" e dispara cinco ações.
- Não permitir desligar. Quem usa leitor de tela ou comando de voz fica refém de ações disparadas sem querer.
- Lógica duplicada no atalho e no botão. Um dia o botão ganha validação nova e o atalho continua salvando sem ela.
- Testar só no seu navegador e no seu teclado. A combinação que funciona no Chrome com layout americano não chega no Firefox ou no ABNT2.
Checklist
- Cada atalho aparece escrito ao lado da ação ou na dica de foco.
- Existe uma lista de atalhos acessível por
?e por um link visível. - Nenhum atalho usa tecla reservada pelo navegador (F3, F5, F11, F12, Ctrl+F e similares).
- Atalhos de tecla única não disparam com foco em campo de texto.
- Existe preferência para desligar atalhos de tecla única.
- Todo atalho aciona um botão que também funciona com clique, Tab e Enter.
- Os atalhos foram testados em Chrome, Edge e Firefox, com teclado ABNT2.
Chame alguém que nunca usou o seu sistema e peça uma tarefa comum: essa pessoa descobre que existe um atalho para ela sem perguntar a ninguém?
Referência: http://www.macoratti.net/vbn_keyp.htm