Skip to content

Commit

Permalink
Merge pull request #1246 from maykinmedia/issue/2376-aria-expanded-de…
Browse files Browse the repository at this point in the history
…sktop-navs

♿ [#2376] Add aria-expanded for desktop navigation menus
  • Loading branch information
alextreme authored Jun 25, 2024
2 parents a847b58 + 57d29d8 commit 451a4e6
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
</div>
{# end of mobile header-menu with logo #}

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

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

<li class="primary-navigation__list-item">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

{% if request.user.is_authenticated %}

<nav class="primary-navigation primary-navigation__authenticated" aria-label="Navigatie na inloggen">
<nav class="primary-navigation primary-navigation--desktop primary-navigation__authenticated" aria-label="Navigatie na inloggen">
<ul class="primary-navigation__list">
<li class="primary-navigation__list-item">
{% 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" %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

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

<nav class="primary-navigation primary-navigation__main" aria-label="Hoofd navigatie">
<nav class="primary-navigation primary-navigation--desktop primary-navigation__main" aria-label="Hoofd navigatie">
<ul class="primary-navigation__list">
{% if cms_apps.products and menu_categories %}
{% if request.user.is_authenticated or not config.hide_categories_from_anonymous_users %}
Expand Down
75 changes: 46 additions & 29 deletions src/open_inwoner/js/components/header/primary-navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ import { Component } from '../abstract/component'
/** @type {string} The primary navigation block name. */
const BLOCK_PRIMARY_NAVIGATION = 'primary-navigation'

/** @type {NodeList<HTMLElement>} The primary navigation block name. */
const PRIMARY_NAVIGATIONS = BEM.getBEMNodes(BLOCK_PRIMARY_NAVIGATION)

/** @type {string} The dismissed modifier state, overrides focus/hover. */
const MODIFIER_DISMISSED = 'dismissed'

/** Handler to bypass Safari bug */
const navigationToggle = document.querySelectorAll(
'.primary-navigation--toggle'
)

/**
* Controls the primary navigation and dismissing it using the escape key.
*/
class PrimaryNavigation extends Component {
constructor(node, initialState = { dismissed: false }) {
super(node, initialState)
/** Handler to bypass Safari bug */
this.navigationToggle = this.node.querySelectorAll(
'.primary-navigation--desktop .primary-navigation--toggle'
)
}

/**
* Binds events to callbacks.
* Callbacks should trigger `setState` which in turn triggers `render`.
Expand All @@ -36,54 +36,71 @@ class PrimaryNavigation extends Component {
* Focusin and Focusout are used instead of Focus for Safari
*/
onFocusOut() {
this.node.classList.remove('primary-navigation--open')
if (this.node) {
BEM.removeModifier(this.node, 'open')
}
this.navigationToggle.forEach((toggle) => {
toggle.setAttribute('aria-expanded', 'false')
})
}

/**
* Gets called when `node` is clicked.
* Clears the dismissed state, (prevents overriding focus/toggle).
*/
toggleDesktopNavOpen() {
this.node.classList.toggle('primary-navigation--open')
// Safari specific
this.node.classList.remove('primary-navigation--dismissed')
this.node.classList.remove('primary-navigation__main--dismissed')
if (this.node) {
const isOpen = BEM.hasModifier(this.node, 'open')
BEM.toggleModifier(this.node, 'open', !isOpen)
BEM.toggleModifier(this.node, MODIFIER_DISMISSED)

if (BLOCK_PRIMARY_NAVIGATION) {
BEM.removeModifier(this.node, MODIFIER_DISMISSED)
}
// Safari specific
this.navigationToggle.forEach((toggle) => {
toggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true')
})
}
}

/**
* Gets called when a key is released.
* If key is escape key, explicitly dismiss the menu (overriding focus/hover).
//* @param {KeyboardEvent} event
* @param {KeyboardEvent} event
*/
onKeyUp(event) {
if (event.key === 'Escape') {
this.setState({ dismissed: true })
this.node.blur()
this.node.classList.remove('primary-navigation--open')
// Safari specific
navigationToggle.forEach((elem) => {
elem.blur()
})
if (this.node) {
this.node.blur()
// Safari specific
this.navigationToggle.forEach((elem) => elem.blur())
}
}
}

/**
* Persists state to DOM.
* Rendering should be one-way traffic and not inspect any current values in DOM.
//* @param {Object} state State to render.
* @param {Object} state State to render.
*/
render(state) {
BEM.toggleModifier(this.node, MODIFIER_DISMISSED, state.dismissed)

if (state.dismissed) {
this.node.blur()
if (this.node) {
BEM.toggleModifier(this.node, MODIFIER_DISMISSED, state.dismissed)

return this.node.querySelector('.primary-navigation--toggle')
if (state.dismissed) {
this.node.blur()
}
}
}
}

// Start!
;[...PRIMARY_NAVIGATIONS].forEach(
(node) => new PrimaryNavigation(node, { dismissed: false })
)
document.addEventListener('DOMContentLoaded', () => {
BEM.getBEMNodes(BLOCK_PRIMARY_NAVIGATION).forEach((node) => {
if (node) {
new PrimaryNavigation(node, { dismissed: false })
}
})
})

0 comments on commit 451a4e6

Please sign in to comment.