pages.keyboardNavigation.title
pages.keyboardNavigation.description
pages.keyboardNavigation.shortcuts.title
- Tab
- pages.keyboardNavigation.shortcuts.tab
- Shift + Tab
- pages.keyboardNavigation.shortcuts.shiftTab
- Entrée / Espace
- pages.keyboardNavigation.shortcuts.enter
- Échap
- pages.keyboardNavigation.shortcuts.escape
- ↑ ↓
- pages.keyboardNavigation.shortcuts.arrows
pages.keyboardNavigation.listNavigation.title
❌ components.exampleToggle.badExample
pages.keyboardNavigation.listNavigation.bad.intro
🏠 pages.keyboardNavigation.listNavigation.bad.items.home
📋 pages.keyboardNavigation.listNavigation.bad.items.projects
👥 pages.keyboardNavigation.listNavigation.bad.items.team
📊 pages.keyboardNavigation.listNavigation.bad.items.stats
⚙️ pages.keyboardNavigation.listNavigation.bad.items.settings
<!-- pages.keyboardNavigation.codeExamples.listNavigation.badComment -->
<div class="menu">
<div tabindex="0">🏠 pages.keyboardNavigation.codeExamples.listNavigation.home</div>
<div tabindex="0">📋 pages.keyboardNavigation.codeExamples.listNavigation.projects</div>
<div tabindex="0">👥 pages.keyboardNavigation.codeExamples.listNavigation.team</div>
<div tabindex="0">📊 pages.keyboardNavigation.codeExamples.listNavigation.stats</div>
<div tabindex="0">⚙️ pages.keyboardNavigation.codeExamples.listNavigation.settings</div>
</div>
<!-- pages.keyboardNavigation.codeExamples.listNavigation.userMustTab5Times -->
<!-- pages.keyboardNavigation.codeExamples.listNavigation.noArrowNavigation -->
<!-- pages.keyboardNavigation.codeExamples.listNavigation.noMenuSemantics -->✅ components.exampleToggle.goodExample
pages.keyboardNavigation.listNavigation.good.intro
🏠 pages.keyboardNavigation.listNavigation.bad.items.home
📋 pages.keyboardNavigation.listNavigation.bad.items.projects
👥 pages.keyboardNavigation.listNavigation.bad.items.team
📊 pages.keyboardNavigation.listNavigation.bad.items.stats
⚙️ pages.keyboardNavigation.listNavigation.bad.items.settings
💡 pages.keyboardNavigation.listNavigation.good.hint
<!-- pages.keyboardNavigation.codeExamples.listNavigation.goodComment -->
<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>// pages.keyboardNavigation.codeExamples.listNavigation.arrowNavigationComment
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
}
}components.exampleToggle.explanation pages.keyboardNavigation.listNavigation.explanation
pages.keyboardNavigation.focusStyles.title
❌ components.exampleToggle.badExample
pages.keyboardNavigation.focusStyles.intro
/* ❌ pages.keyboardNavigation.codeExamples.focusIndicators.removeFocusComment */
*:focus {
outline: none !important;
}
button:focus,
a:focus,
input:focus {
outline: none !important;
}<!-- pages.keyboardNavigation.codeExamples.focusIndicators.accessibilityProblems -->
<button>pages.keyboardNavigation.codeExamples.focusIndicators.button1</button> <!-- pages.keyboardNavigation.codeExamples.focusIndicators.button1NoType -->
<button>pages.keyboardNavigation.codeExamples.focusIndicators.button2</button> <!-- pages.keyboardNavigation.codeExamples.focusIndicators.button2NoType -->
<a href="#">pages.keyboardNavigation.codeExamples.focusIndicators.link</a> <!-- pages.keyboardNavigation.codeExamples.focusIndicators.linkNoFocus -->
<input type="text" /> <!-- pages.keyboardNavigation.codeExamples.focusIndicators.inputNoFocus -->
<!-- pages.keyboardNavigation.codeExamples.focusIndicators.keyboardNavigationNotVisible -->✅ components.exampleToggle.goodExample
pages.keyboardNavigation.focusStyles.intro
/* ✅ pages.keyboardNavigation.codeExamples.focusIndicators.visibleFocusComment */
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">pages.keyboardNavigation.codeExamples.focusIndicators.button1</button>
<button type="button">pages.keyboardNavigation.codeExamples.focusIndicators.button2</button>
<a href="#">pages.keyboardNavigation.focusStyles.link</a>
<input type="text" placeholder="pages.keyboardNavigation.focusStyles.input" />components.exampleToggle.explanation pages.keyboardNavigation.focusStyles.explanation
pages.keyboardNavigation.skipLink.title
❌ components.exampleToggle.badExample
pages.keyboardNavigation.skipLink.bad.logo
pages.keyboardNavigation.skipLink.bad.nav.homepages.keyboardNavigation.skipLink.bad.nav.productspages.keyboardNavigation.skipLink.bad.nav.servicespages.keyboardNavigation.skipLink.bad.nav.aboutpages.keyboardNavigation.skipLink.bad.nav.blogpages.keyboardNavigation.skipLink.bad.nav.contactpages.keyboardNavigation.skipLink.bad.nav.supportpages.keyboardNavigation.skipLink.bad.nav.account
pages.keyboardNavigation.skipLink.bad.content.heading
pages.keyboardNavigation.skipLink.bad.content.description
<!-- pages.keyboardNavigation.codeExamples.skipLinks.badComment -->
<header>
<nav>
<a href="#">pages.keyboardNavigation.codeExamples.skipLinks.home</a>
<a href="#">pages.keyboardNavigation.codeExamples.skipLinks.products</a>
<a href="#">pages.keyboardNavigation.codeExamples.skipLinks.services</a>
<!-- pages.keyboardNavigation.codeExamples.skipLinks.tenPlusLinks -->
</nav>
</header>
<main>
<!-- pages.keyboardNavigation.codeExamples.skipLinks.userMustTraverse -->
<h1>pages.keyboardNavigation.codeExamples.skipLinks.mainContent</h1>
</main>✅ components.exampleToggle.goodExample
pages.keyboardNavigation.skipLink.skip
pages.keyboardNavigation.skipLink.bad.logo
pages.keyboardNavigation.skipLink.bad.nav.homepages.keyboardNavigation.skipLink.bad.nav.productspages.keyboardNavigation.skipLink.bad.nav.servicespages.keyboardNavigation.skipLink.bad.nav.aboutpages.keyboardNavigation.skipLink.bad.nav.blogpages.keyboardNavigation.skipLink.bad.nav.contactpages.keyboardNavigation.skipLink.bad.nav.supportpages.keyboardNavigation.skipLink.bad.nav.account
pages.keyboardNavigation.skipLink.good.content.heading
pages.keyboardNavigation.skipLink.good.content.description
/* pages.keyboardNavigation.codeExamples.skipLinks.skipLinkComment */
.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">
pages.keyboardNavigation.codeExamples.skipLinks.skipToContent
</a>
<header>
<nav aria-label="navigation.ariaLabel">
<ul>
<li><a href="/">pages.keyboardNavigation.codeExamples.skipLinks.home</a></li>
<li><a href="/produits">pages.keyboardNavigation.codeExamples.skipLinks.products</a></li>
<li><a href="/services">pages.keyboardNavigation.codeExamples.skipLinks.services</a></li>
</ul>
</nav>
</header>
<main id="main-content">
<h1>pages.keyboardNavigation.codeExamples.skipLinks.mainContent</h1>
</main>components.exampleToggle.explanation pages.keyboardNavigation.skipLink.explanation
pages.keyboardNavigation.modalTrap.title
❌ components.exampleToggle.badExample
<!-- pages.keyboardNavigation.codeExamples.modalTrap.badComment -->
<div v-if="modalOpen" class="modal-overlay" @click="close">
<div class="modal-content" @click.stop>
<div class="modal-header">
<h3>pages.keyboardNavigation.codeExamples.modalTrap.confirmAction</h3>
<button @click="close">×</button>
</div>
<div class="modal-body">
<p>pages.keyboardNavigation.codeExamples.modalTrap.areYouSure</p>
<input type="text" placeholder="pages.keyboardNavigation.modalTrap.modal.reason" />
</div>
<div class="modal-footer">
<button @click="close">pages.keyboardNavigation.codeExamples.modalTrap.cancel</button>
<button @click="confirm">pages.keyboardNavigation.codeExamples.modalTrap.confirm</button>
</div>
</div>
</div>✅ components.exampleToggle.goodExample
<!-- pages.keyboardNavigation.codeExamples.modalTrap.goodComment -->
<div
v-if="modalOpen"
class="modal-overlay"
@click="closeModal"
@keydown.esc="closeModal"
>
<div
class="modal-content"
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
@click.stop
>
<header class="modal-header">
<h2 id="modal-title">pages.keyboardNavigation.codeExamples.modalTrap.confirmAction</h2>
<button
type="button"
@click="closeModal"
aria-label="pages.keyboardNavigation.codeExamples.modalTrap.closeModal"
class="close-btn"
>×</button>
</header>
<div class="modal-body">
<p>pages.keyboardNavigation.codeExamples.modalTrap.areYouSure</p>
<input
ref="firstInput"
type="text"
placeholder="pages.keyboardNavigation.codeExamples.modalTrap.reasonOptional"
@keydown.tab="handleFocusTrap"
/>
</div>
<footer class="modal-footer">
<button
type="button"
@click="closeModal"
@keydown.tab="handleFocusTrap"
>pages.keyboardNavigation.codeExamples.modalTrap.cancel</button>
<button
type="button"
ref="lastButton"
@click="confirmAction"
@keydown.tab="handleFocusTrap"
>pages.keyboardNavigation.codeExamples.modalTrap.confirm</button>
</footer>
</div>
</div>// pages.keyboardNavigation.codeExamples.modalTrap.focusTrapComment :
// - pages.keyboardNavigation.codeExamples.modalTrap.autoFocus
// - pages.keyboardNavigation.codeExamples.modalTrap.trapFocus
// - pages.keyboardNavigation.codeExamples.modalTrap.closeOnEscape
// - pages.keyboardNavigation.codeExamples.modalTrap.returnFocus
function handleFocusTrap(event) {
const focusableElements = modalContent.querySelectorAll(
'button, input, [tabindex]:not([tabindex="-1"])'
)
const firstElement = focusableElements[0]
const lastElement = focusableElements[focusableElements.length - 1]
if (event.shiftKey && document.activeElement === firstElement) {
event.preventDefault()
lastElement.focus()
} else if (!event.shiftKey && document.activeElement === lastElement) {
event.preventDefault()
firstElement.focus()
}
}components.exampleToggle.explanation pages.keyboardNavigation.modalTrap.explanation