fix: support keyboard navigation for menus (#988)
This commit is contained in:
parent
a61602e94a
commit
c55c466e17
|
@ -13,8 +13,6 @@
|
|||
|
||||
|
||||
<div class="wrapper">
|
||||
<input type="checkbox" class="hidden" id="menu-header-control" />
|
||||
|
||||
{{ partial "site-header" (dict "Root" . "MenuEnabled" false) }}
|
||||
|
||||
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
<div
|
||||
class="wrapper {{ if default false .Site.Params.geekdocDarkModeDim }}dark-mode-dim{{ end }}"
|
||||
>
|
||||
<input type="checkbox" class="hidden" id="menu-control" />
|
||||
<input type="checkbox" class="hidden" id="menu-header-control" />
|
||||
{{ $navEnabled := default true .Page.Params.geekdocNav }}
|
||||
{{ partial "site-header" (dict "Root" . "MenuEnabled" $navEnabled) }}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{ if hugo.IsMultilingual }}
|
||||
<span class="gdoc-language">
|
||||
<ul class="gdoc-language__selector" role="button" aria-pressed="false" tabindex="0">
|
||||
<ul class="gdoc-language__selector" tabindex="0" role="button" aria-pressed="false">
|
||||
<li>
|
||||
{{ range .Site.Languages }}
|
||||
{{ if eq . $.Site.Language }}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
<header class="gdoc-header">
|
||||
<div class="container flex align-center justify-between">
|
||||
{{ if .MenuEnabled }}
|
||||
<label for="menu-control" class="gdoc-nav__control" tabindex="0">
|
||||
<svg class="gdoc-icon gdoc_menu">
|
||||
<title>{{ i18n "button_nav_open" }}</title>
|
||||
<use xlink:href="#gdoc_menu"></use>
|
||||
</svg>
|
||||
<svg class="gdoc-icon gdoc_arrow_back">
|
||||
<title>{{ i18n "button_nav_close" }}</title>
|
||||
<use xlink:href="#gdoc_arrow_back"></use>
|
||||
</svg>
|
||||
<label for="menu-control" class="gdoc-nav__control">
|
||||
<div tabindex="0" role="button" aria-pressed="false">
|
||||
<input type="checkbox" class="hidden" id="menu-control" />
|
||||
|
||||
<svg class="gdoc-icon gdoc_menu">
|
||||
<title>{{ i18n "button_nav_open" }}</title>
|
||||
<use xlink:href="#gdoc_menu"></use>
|
||||
</svg>
|
||||
<svg class="gdoc-icon gdoc_arrow_back">
|
||||
<title>{{ i18n "button_nav_close" }}</title>
|
||||
<use xlink:href="#gdoc_arrow_back"></use>
|
||||
</svg>
|
||||
</div>
|
||||
</label>
|
||||
{{ end }}
|
||||
<div>
|
||||
|
@ -24,14 +28,14 @@
|
|||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="gdoc-menu-header">
|
||||
<div class="gdoc-menu-header flex gap-16">
|
||||
<span class="gdoc-menu-header__items">
|
||||
{{ if .Root.Site.Data.menu.extra.header }}
|
||||
{{ partial "menu-extra" (dict "current" .Root "source" .Root.Site.Data.menu.extra.header "target" "header") }}
|
||||
{{ end }}
|
||||
|
||||
|
||||
<span id="gdoc-color-theme">
|
||||
<span id="gdoc-color-theme" tabindex="0" role="button" aria-pressed="false">
|
||||
<svg class="gdoc-icon gdoc_brightness_dark">
|
||||
<title>{{ i18n "button_toggle_dark" }}</title>
|
||||
<use xlink:href="#gdoc_brightness_dark"></use>
|
||||
|
@ -56,23 +60,24 @@
|
|||
</span>
|
||||
|
||||
{{ partial "language" .Root }}
|
||||
</span>
|
||||
<span class="gdoc-menu-header__control">
|
||||
<label for="menu-header-control">
|
||||
<div tabindex="0" role="button" aria-pressed="false">
|
||||
<input type="checkbox" class="hidden" id="menu-header-control" />
|
||||
|
||||
|
||||
<span class="gdoc-menu-header__control">
|
||||
<label for="menu-header-control">
|
||||
<svg class="gdoc-icon gdoc_keyboard_arrow_right">
|
||||
<use xlink:href="#gdoc_keyboard_arrow_right"></use>
|
||||
<title>{{ i18n "button_menu_close" }}</title>
|
||||
</svg>
|
||||
</label>
|
||||
</span>
|
||||
|
||||
<svg class="gdoc-icon gdoc_keyboard_arrow_left">
|
||||
<use xlink:href="#gdoc_keyboard_arrow_left"></use>
|
||||
<title>{{ i18n "button_menu_open" }}</title>
|
||||
</svg>
|
||||
</div>
|
||||
</label>
|
||||
</span>
|
||||
<label for="menu-header-control" class="gdoc-menu-header__control">
|
||||
<svg class="gdoc-icon gdoc_keyboard_arrow_left">
|
||||
<use xlink:href="#gdoc_keyboard_arrow_left"></use>
|
||||
<title>{{ i18n "button_menu_open" }}</title>
|
||||
</svg>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Find all elements with role="button"
|
||||
const buttonRoleElements = document.querySelectorAll('[role="button"]')
|
||||
|
||||
const gdocNav = document.querySelector(".gdoc-nav")
|
||||
const gdocPage = document.querySelector(".gdoc-page")
|
||||
|
||||
buttonRoleElements.forEach((buttonElement) => {
|
||||
// Check if this button controls a checkbox
|
||||
const controlId = buttonElement.parentElement.getAttribute("for")
|
||||
if (!controlId) return
|
||||
|
||||
const controlElement = document.getElementById(controlId)
|
||||
if (!controlElement || controlElement.type !== "checkbox") return
|
||||
|
||||
// Set initial accessibility state
|
||||
buttonElement.setAttribute("aria-pressed", controlElement.checked)
|
||||
|
||||
if (controlId === "menu-control" && gdocNav && gdocPage) {
|
||||
updateMenuAccessibility(controlElement.checked)
|
||||
}
|
||||
|
||||
buttonElement.addEventListener("click", function () {
|
||||
this.setAttribute("aria-pressed", controlElement.checked)
|
||||
|
||||
if (controlId === "menu-control" && gdocNav && gdocPage) {
|
||||
updateMenuAccessibility(controlElement.checked)
|
||||
}
|
||||
})
|
||||
|
||||
buttonElement.addEventListener("keydown", function (event) {
|
||||
if (event.key === "Enter") {
|
||||
controlElement.checked = !controlElement.checked
|
||||
this.setAttribute("aria-pressed", controlElement.checked)
|
||||
|
||||
if (controlId === "menu-control" && gdocNav && gdocPage) {
|
||||
updateMenuAccessibility(controlElement.checked)
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Helper function for menu navigation accessibility
|
||||
function updateMenuAccessibility(isMenuOpen) {
|
||||
if (!gdocNav || !gdocPage) return
|
||||
|
||||
if (isMenuOpen) {
|
||||
gdocNav.removeAttribute("inert")
|
||||
gdocNav.setAttribute("aria-hidden", false)
|
||||
|
||||
gdocPage.setAttribute("inert", "")
|
||||
gdocPage.setAttribute("aria-hidden", true)
|
||||
} else {
|
||||
gdocNav.setAttribute("inert", "")
|
||||
gdocNav.setAttribute("aria-hidden", true)
|
||||
|
||||
gdocPage.removeAttribute("inert")
|
||||
gdocPage.setAttribute("aria-hidden", false)
|
||||
}
|
||||
}
|
||||
})
|
|
@ -7,7 +7,7 @@ import { TOGGLE_COLOR_THEMES, THEME, COLOR_THEME_AUTO } from "./config.js"
|
|||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const colorThemeToggle = document.getElementById("gdoc-color-theme")
|
||||
|
||||
colorThemeToggle.onclick = function () {
|
||||
function toggleColorTheme() {
|
||||
let lstore = Storage.namespace(THEME)
|
||||
let currentColorTheme = lstore.get("color-theme") || COLOR_THEME_AUTO
|
||||
let nextColorTheme = toggle(TOGGLE_COLOR_THEMES, currentColorTheme)
|
||||
|
@ -15,6 +15,17 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||
lstore.set("color-theme", TOGGLE_COLOR_THEMES[nextColorTheme])
|
||||
applyTheme(false)
|
||||
}
|
||||
|
||||
colorThemeToggle.onclick = function () {
|
||||
toggleColorTheme()
|
||||
}
|
||||
|
||||
colorThemeToggle.addEventListener("keydown", function (event) {
|
||||
if (event.key === "Enter") {
|
||||
toggleColorTheme()
|
||||
event.preventDefault()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
function applyTheme(init = true) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Clipboard from "clipboard"
|
||||
import "./accessibility.js"
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
let clipboard = new Clipboard(".clip")
|
||||
|
|
|
@ -31,6 +31,12 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
&__control {
|
||||
svg.gdoc-icon.gdoc_keyboard_arrow_right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__control,
|
||||
&__home {
|
||||
display: flex;
|
||||
|
@ -76,7 +82,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#menu-control:checked ~ main {
|
||||
.wrapper:has(#menu-control:checked) {
|
||||
.gdoc-nav nav,
|
||||
.gdoc-page {
|
||||
transform: translateX(defaults.$menu-width);
|
||||
|
@ -85,9 +91,7 @@
|
|||
.gdoc-page {
|
||||
opacity: 0.25;
|
||||
}
|
||||
}
|
||||
|
||||
#menu-control:checked ~ .gdoc-header .gdoc-nav__control {
|
||||
svg.gdoc-icon.gdoc_menu {
|
||||
display: none;
|
||||
}
|
||||
|
@ -97,7 +101,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#menu-header-control:checked ~ .gdoc-header {
|
||||
.wrapper:has(#menu-header-control:checked) {
|
||||
.gdoc-brand {
|
||||
display: none;
|
||||
}
|
||||
|
@ -111,6 +115,9 @@
|
|||
svg.gdoc-icon.gdoc_keyboard_arrow_left {
|
||||
display: none;
|
||||
}
|
||||
svg.gdoc-icon.gdoc_keyboard_arrow_right {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ var config = {
|
|||
generate(seed, files) {
|
||||
let manifest = {}
|
||||
|
||||
files.forEach(function (element, index) {
|
||||
files.forEach(function (element) {
|
||||
if (element.name.endsWith("VERSION")) return
|
||||
if (element.name.endsWith(".svg")) return
|
||||
if (element.name.startsWith("fonts/")) return
|
||||
|
|
Loading…
Reference in New Issue