Atalhos de teclado

Tab
Navegar entre elementos interativos
Shift + Tab
Navegação para trás
Entrée / Espace
Ativar botões e links
Échap
Fechar modais e menus
↑ ↓
Navegar em listas e menus

Navegação por teclado em listas

Exemplo ruim

Menu apenas com navegação por Tab:

<!-- Ruim: Apenas navegação por Tab -->
<div class="menu">
  <div tabindex="0">🏠 Início</div>
  <div tabindex="0">📋 Projetos</div>
  <div tabindex="0">👥 Equipe</div>
  <div tabindex="0">📊 Estatísticas</div>
  <div tabindex="0">⚙️ Configurações</div>
</div>

<!-- Usuário deve pressionar Tab 5 vezes -->
<!-- Sem navegação por setas -->
<!-- Sem semântica de menu -->

Exemplo bom

Menu com navegação por setas:

💡 Use ↑ ↓ para navegar, Enter para selecionar

<!-- Bom: navegação por setas com roving tabindex -->
<div
  role="menu"
  @keydown="handleKeydown"
>
  <div
    v-for="(item, i) in items"
    role="menuitem"
    :tabindex="selected === i ? 0 : -1"
    @focus="selected = i"
    :class="{ selected: selected === i }"
  >
    {{ item }}
  </div>
</div>
// Navegação por setas com roving tabindex
function handleKeydown(e) {
  switch(e.key) {
    case 'ArrowDown':
      selected = (selected + 1) % items.length
      break
    case 'ArrowUp':
      selected = selected === 0
        ? items.length - 1
        : selected - 1
      break
    case 'Enter':
      selectItem(selected)
      break
  }
}

Explicação: Listas navegáveis por teclado permitem usar as setas para mover entre elementos, além da navegação clássica por Tab.

Estilos de foco visíveis

Exemplo ruim

Tente navegar com Tab nesta área:

Link para página
/* ❌ Remove todos os indicadores de foco */
*:focus {
  outline: none !important;
}

button:focus,
a:focus,
input:focus {
  outline: none !important;
}
<!-- ❌ Problemas de acessibilidade: -->
<button>Botão 1</button>        <!-- Sem tipo, foco invisível -->
<button>Botão 2</button>        <!-- Sem tipo, foco invisível -->
<a href="#">Link</a>           <!-- Foco invisível -->
<input type="text" />         <!-- Foco invisível -->

<!-- Navegação por teclado impossível de acompanhar visualmente -->

Exemplo bom

Tente navegar com Tab nesta área:

Link para página
/* ✅ Indicadores de foco visíveis e acessíveis */
button:focus-visible {
  outline: 3px solid #4F46E5;
  outline-offset: 2px;
}

input:focus-visible {
  border-color: #4F46E5;
  outline: 2px solid #4F46E5;
  outline-offset: 1px;
}
<button type="button">Botão 1</button>
<button type="button">Botão 2</button>
<a href="#">Link para página</a>
<input type="text" placeholder="Digite o texto" />

Explicação: Usuários navegando por teclado precisam de indicadores visuais claros para saber onde estão na página.

Link de salto (Pular para conteúdo)

Exemplo ruim

Conteúdo principal

O usuário deve navegar por todos os links de navegação...

<!-- Ruim: sem link de salto -->
<header>
  <nav>
    <a href="#">Início</a>
    <a href="#">Produtos</a>
    <a href="#">Serviços</a>
    <!-- Mais de 10 links de navegação... -->
  </nav>
</header>
<main>
  <!-- Usuário deve atravessar toda a navegação -->
  <h1>Conteúdo principal</h1>
</main>

Exemplo bom

Conteúdo principal

O usuário pode acessar diretamente aqui graças ao link de salto!

/* Link de salto oculto por padrão, visível ao focar */
.skip-link {
  position: absolute;
  top: -100px;
  left: 1rem;
  z-index: 1000;
  padding: 0.5rem 1rem;
  background: var(--color-primary);
  color: white;
  text-decoration: none;
  border-radius: 0.625rem;
}

.skip-link:focus {
  top: 1rem;
}
<a href="#main-content" class="skip-link">
  Pular para conteúdo principal
</a>
<header>
  <nav aria-label="Navegação principal">
    <ul>
      <li><a href="/">Início</a></li>
      <li><a href="/produits">Produtos</a></li>
      <li><a href="/services">Serviços</a></li>
    </ul>
  </nav>
</header>
<main id="main-content">
  <h1>Conteúdo principal</h1>
</main>

Explicação: Links de salto permitem que usuários de teclado pulem diretamente para o conteúdo principal sem ter que passar por toda a navegação.

Modal com armadilha de foco

Exemplo ruim

Exemplo bom

Explicação: Modais devem manter o foco dentro e permitir fechar com a tecla Escape. O foco deve retornar ao elemento que abriu o modal.