Skip to content

Commit 451a4e6

Browse files
authored
Merge pull request #1246 from maykinmedia/issue/2376-aria-expanded-desktop-navs
♿ [#2376] Add aria-expanded for desktop navigation menus
2 parents a847b58 + 57d29d8 commit 451a4e6

File tree

4 files changed

+50
-33
lines changed

4 files changed

+50
-33
lines changed

src/open_inwoner/components/templates/components/Header/Header.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
</div>
3333
{# end of mobile header-menu with logo #}
3434

35-
<div class="header__submenu">
35+
<div class="header--mobile header__submenu">
3636
{% if cms_apps.products and request.user.is_authenticated or not config.hide_search_from_anonymous_users %}
3737
<nav class="header__actions header__actions--open" aria-label="Zoek navigatie mobiel">
3838
<form id="search-form-mobile-open" class="search-form-delegate form form--inline">
@@ -42,7 +42,7 @@
4242
</nav>
4343
{% endif %}
4444

45-
<nav class="primary-navigation" aria-label="Hoofd navigatie">
45+
<nav class="primary-navigation primary-navigation--mobile" aria-label="Hoofd navigatie">
4646
<ul class="primary-navigation__list">
4747

4848
<li class="primary-navigation__list-item">

src/open_inwoner/components/templates/components/Header/NavigationAuthenticated.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
{% if request.user.is_authenticated %}
66

7-
<nav class="primary-navigation primary-navigation__authenticated" aria-label="Navigatie na inloggen">
7+
<nav class="primary-navigation primary-navigation--desktop primary-navigation__authenticated" aria-label="Navigatie na inloggen">
88
<ul class="primary-navigation__list">
99
<li class="primary-navigation__list-item">
1010
{% button text=_('Welkom ')|addstr:request.user.get_short_name type="button" icon="expand_more" icon_position="after" icon_outlined=True transparent=True extra_classes="primary-navigation--toggle" %}

src/open_inwoner/components/templates/components/Header/PrimaryNavigation.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
{% get_solo "configurations.SiteConfiguration" as config %}
44

5-
<nav class="primary-navigation primary-navigation__main" aria-label="Hoofd navigatie">
5+
<nav class="primary-navigation primary-navigation--desktop primary-navigation__main" aria-label="Hoofd navigatie">
66
<ul class="primary-navigation__list">
77
{% if cms_apps.products and menu_categories %}
88
{% if request.user.is_authenticated or not config.hide_categories_from_anonymous_users %}

src/open_inwoner/js/components/header/primary-navigation.js

+46-29
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import { Component } from '../abstract/component'
44
/** @type {string} The primary navigation block name. */
55
const BLOCK_PRIMARY_NAVIGATION = 'primary-navigation'
66

7-
/** @type {NodeList<HTMLElement>} The primary navigation block name. */
8-
const PRIMARY_NAVIGATIONS = BEM.getBEMNodes(BLOCK_PRIMARY_NAVIGATION)
9-
107
/** @type {string} The dismissed modifier state, overrides focus/hover. */
118
const MODIFIER_DISMISSED = 'dismissed'
129

13-
/** Handler to bypass Safari bug */
14-
const navigationToggle = document.querySelectorAll(
15-
'.primary-navigation--toggle'
16-
)
17-
1810
/**
1911
* Controls the primary navigation and dismissing it using the escape key.
2012
*/
2113
class PrimaryNavigation extends Component {
14+
constructor(node, initialState = { dismissed: false }) {
15+
super(node, initialState)
16+
/** Handler to bypass Safari bug */
17+
this.navigationToggle = this.node.querySelectorAll(
18+
'.primary-navigation--desktop .primary-navigation--toggle'
19+
)
20+
}
21+
2222
/**
2323
* Binds events to callbacks.
2424
* Callbacks should trigger `setState` which in turn triggers `render`.
@@ -36,54 +36,71 @@ class PrimaryNavigation extends Component {
3636
* Focusin and Focusout are used instead of Focus for Safari
3737
*/
3838
onFocusOut() {
39-
this.node.classList.remove('primary-navigation--open')
39+
if (this.node) {
40+
BEM.removeModifier(this.node, 'open')
41+
}
42+
this.navigationToggle.forEach((toggle) => {
43+
toggle.setAttribute('aria-expanded', 'false')
44+
})
4045
}
4146

4247
/**
4348
* Gets called when `node` is clicked.
4449
* Clears the dismissed state, (prevents overriding focus/toggle).
4550
*/
4651
toggleDesktopNavOpen() {
47-
this.node.classList.toggle('primary-navigation--open')
48-
// Safari specific
49-
this.node.classList.remove('primary-navigation--dismissed')
50-
this.node.classList.remove('primary-navigation__main--dismissed')
52+
if (this.node) {
53+
const isOpen = BEM.hasModifier(this.node, 'open')
54+
BEM.toggleModifier(this.node, 'open', !isOpen)
55+
BEM.toggleModifier(this.node, MODIFIER_DISMISSED)
56+
57+
if (BLOCK_PRIMARY_NAVIGATION) {
58+
BEM.removeModifier(this.node, MODIFIER_DISMISSED)
59+
}
60+
// Safari specific
61+
this.navigationToggle.forEach((toggle) => {
62+
toggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true')
63+
})
64+
}
5165
}
5266

5367
/**
5468
* Gets called when a key is released.
5569
* If key is escape key, explicitly dismiss the menu (overriding focus/hover).
56-
//* @param {KeyboardEvent} event
70+
* @param {KeyboardEvent} event
5771
*/
5872
onKeyUp(event) {
5973
if (event.key === 'Escape') {
6074
this.setState({ dismissed: true })
61-
this.node.blur()
62-
this.node.classList.remove('primary-navigation--open')
63-
// Safari specific
64-
navigationToggle.forEach((elem) => {
65-
elem.blur()
66-
})
75+
if (this.node) {
76+
this.node.blur()
77+
// Safari specific
78+
this.navigationToggle.forEach((elem) => elem.blur())
79+
}
6780
}
6881
}
6982

7083
/**
7184
* Persists state to DOM.
7285
* Rendering should be one-way traffic and not inspect any current values in DOM.
73-
//* @param {Object} state State to render.
86+
* @param {Object} state State to render.
7487
*/
7588
render(state) {
76-
BEM.toggleModifier(this.node, MODIFIER_DISMISSED, state.dismissed)
77-
78-
if (state.dismissed) {
79-
this.node.blur()
89+
if (this.node) {
90+
BEM.toggleModifier(this.node, MODIFIER_DISMISSED, state.dismissed)
8091

81-
return this.node.querySelector('.primary-navigation--toggle')
92+
if (state.dismissed) {
93+
this.node.blur()
94+
}
8295
}
8396
}
8497
}
8598

8699
// Start!
87-
;[...PRIMARY_NAVIGATIONS].forEach(
88-
(node) => new PrimaryNavigation(node, { dismissed: false })
89-
)
100+
document.addEventListener('DOMContentLoaded', () => {
101+
BEM.getBEMNodes(BLOCK_PRIMARY_NAVIGATION).forEach((node) => {
102+
if (node) {
103+
new PrimaryNavigation(node, { dismissed: false })
104+
}
105+
})
106+
})

0 commit comments

Comments
 (0)