Skip to content

Commit

Permalink
Revert "Refactor dropwdown link for accessibility"
Browse files Browse the repository at this point in the history
This reverts commit 8d8db5b.
  • Loading branch information
Ben Morse committed Feb 16, 2024
1 parent 391de87 commit d703343
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 148 deletions.
Original file line number Diff line number Diff line change
@@ -1,33 +1,51 @@
{% load static wagtailcore_tags localization bg_nav_tags wagtailimages_tags i18n %}
<div class="pni-category-dropdown tw-hidden tw-relative">
<button
class="
tw-inline-flex
pni-category-dropdown-button
tw-bg-transparent
tw-items-center
tw-relative
tw-pr-10
tw-py-4
tw-mr-auto
tw-font-sans
tw-font-bold
tw-text-sm
tw-group
hover:tw-text-black
tw-text-gray-40
"
aria-controls="pni-category-dropdown-select"
aria-expanded="false"
aria-label="{% trans 'Open category dropdown' %}"
data-aria-close-label="{% trans 'Close category dropdown' %}"
>
<span>{% trans "More Categories" %}</span>
<svg aria-hidden="true" focusable="false" width="11" height="7" viewBox="0 0 11 7" fill="none" xmlns="http://www.w3.org/2000/svg" class="tw-ml-4 tw-origin-center tw-stroke-gray-40 group-hover:tw-stroke-black">
<path d="M1 1L5.02504 5.02504L9.05007 1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<ul id="pni-category-dropdown-select" class="tw-hidden tw-list-none tw-absolute tw-top-full tw-w-auto tw-right-0 tw-p-0 tw-z-50 tw-border-gray-20 tw-border tw-pb-4 tw-bg-white">

<button
class="
pni-category-dropdown
tw-hidden
tw-bg-transparent
tw-items-center
tw-relative
tw-pr-10
tw-py-4
tw-mr-auto
tw-font-sans
tw-font-bold
tw-text-sm
tw-group
hover:tw-text-black
tw-text-gray-40
"
>
<span>{% trans "More Categories" %}</span>
<svg width="11" height="7" viewBox="0 0 11 7" fill="none" xmlns="http://www.w3.org/2000/svg" class="tw-ml-4 tw-origin-center tw-stroke-gray-40 group-hover:tw-stroke-black">
<title>{% trans "Open category drop down" %}</title>
<path d="M1 1L5.02504 5.02504L9.05007 1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<ul id="pni-category-dropdown-select" class="tw-hidden tw-list-none tw-absolute tw-right-0 tw-p-0 tw-top-0 tw-z-50 tw-border-gray-20 tw-border tw-pb-4 tw-bg-white">
<li class="
tw-bg-white
tw-w-full
tw-mr-0
tw-font-sans
tw-font-bold
tw-no-underline
tw-px-8
tw-py-4
tw-mb-0
tw-text-black
tw-flex
tw-items-center
tw-justify-end
tw-text-sm
">
<span>{% trans "More Categories" %}</span>
<svg width="11" height="7" viewBox="0 0 11 7" fill="none" xmlns="http://www.w3.org/2000/svg" class="tw-ml-4 tw-origin-center tw-stroke-black tw-rotate-180">
<title>{% trans "Close category drop down" %}</title>
<path d="M1 1L5.02504 5.02504L9.05007 1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</li>
</ul>
</div>

</button>
153 changes: 35 additions & 118 deletions source/js/buyers-guide/template-js-handler/pni-category-dropdown.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
// TODO Refactor to ES6 Class in future to match other components and include aria/keyboard shortcuts

export default () => {
const dropdown = document.querySelector(".pni-category-dropdown");
const dropdownButton = dropdown.querySelector(".pni-category-dropdown-button");
const dropdownButtonAriaCloseText = dropdownButton.getAttribute("data-aria-close-label");
const dropdownButtonAriaOpenText = dropdownButton.getAttribute("data-aria-close-label");
const dropdownButtonChevron = dropdownButton.querySelector("svg");
const dropdownSelect = dropdown.querySelector("#pni-category-dropdown-select");
let defaultDropdownHeaderText; // Keep track of dropdown button's default text for different locales

const navLinkMargin = 20; // Calculate which items go into the dropdown

// Need this to keep track of the default text of the dropdown button when using different locales
let defaultDropdownHeaderText;

// Needed for calculating which items go into the dropdown
const navLinkMargin = 20;
const categoryWrapper = document.querySelector("#pni-category-wrapper");
const categoryNav = document.querySelector("#product-review");

// Calculate width and margin
const calculateWidthAndMargin = (ele) => ele.clientWidth + navLinkMargin;

// Resize category navigation
const resizeCategoryNavigation = () => {
const dropdownSelect = document.querySelector(
"#pni-category-dropdown-select"
);
const dropdownSelectItems = document.querySelectorAll(
"#pni-category-dropdown-select > li, #pni-category-dropdown-select > li > a"
);

function resizeCategoryNavigation() {
const categoryLinks = [
...document.querySelectorAll(
"#buyersguide-category-link-container > .multipage-link"
Expand All @@ -40,10 +45,9 @@ export default () => {
}

linksForDropdown.forEach((e) => addCategoryToDropdown(e));
};
}

// Add category to dropdown
const addCategoryToDropdown = (category) => {
function addCategoryToDropdown(category) {
const el = document.createElement("li");
el.classList.add(
"tw-bg-white",
Expand All @@ -62,15 +66,15 @@ export default () => {
category.classList.remove("tw-block");
el.append(category);
dropdownSelect.append(el);
};
}

// Highlight selected category
const highlightSelectedCategory = () => {
function highlightSelectedCategory() {
const activeCategory = document.querySelector(
"#pni-category-dropdown-select .active"
);

const dropdownHeaderText = document.querySelector(
".pni-category-dropdown-button > span"
".pni-category-dropdown > span"
);

if (activeCategory) {
Expand All @@ -80,34 +84,11 @@ export default () => {
dropdownHeaderText.innerText = defaultDropdownHeaderText;
dropdownHeaderText.classList.remove("tw-text-black");
}
};

// Open menu
const openMenu = (withFocus = false) => {
dropdownSelect.classList.remove("tw-hidden");
dropdownButton.setAttribute('aria-expanded', 'true');
dropdownButtonChevron.classList.add("tw-stroke-black", "tw-rotate-180");
dropdownButton.setAttribute('aria-label', dropdownButtonAriaCloseText);

if (withFocus) {
const firstOption = dropdownSelect.querySelector("li > a");
if (firstOption) {
firstOption.focus();
}
}
};

// Close menu
const closeMenu = () => {
dropdownSelect.classList.add("tw-hidden");
dropdownButton.setAttribute('aria-expanded', 'false');
dropdownButtonChevron.classList.remove("tw-stroke-black", "tw-rotate-180");
dropdownButton.setAttribute('aria-label', dropdownButtonAriaOpenText);
};

if (dropdown && dropdownButton && dropdownSelect) {
// removing styling that are exclusively used when JS is disabled or before it is loaded
dropdown.classList.add("tw-block");
}

if (dropdown) {
// removing styling that are exclusive used when JS is disabled or before it is loaded
dropdown.classList.add("tw-inline-flex");
dropdown.classList.remove("tw-hidden");
categoryWrapper.classList.add("tw-w-max", "tw-min-w-full");
document
Expand All @@ -120,7 +101,7 @@ export default () => {
);

defaultDropdownHeaderText = document.querySelector(
".pni-category-dropdown-button > span"
".pni-category-dropdown > span"
).innerText;

// If there is an overflow of categories lets start moving them to the category dropdown
Expand All @@ -129,7 +110,7 @@ export default () => {
highlightSelectedCategory();
}

// Detect class changes within links
// Using to detect classes changes within the links
new MutationObserver(() => {
highlightSelectedCategory();
}).observe(dropdownSelect, {
Expand All @@ -138,87 +119,23 @@ export default () => {
attributes: true,
});

// Support adjusting screen size (avoid having to refresh the page)
// So people can test going to smaller screen sizes without having to refresh the page
window.onresize = function () {
if (categoryWrapper.clientWidth > categoryNav.clientWidth) {
resizeCategoryNavigation();
highlightSelectedCategory();
}
};

// Event listener for keyboard events on dropdown button
dropdownButton.addEventListener("keydown", function (event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
if (dropdownButton.getAttribute('aria-expanded') === 'false') {
openMenu(withFocus = true);
} else {
closeMenu();
}
}

if (event.key === 'ArrowDown') {
if (dropdownButton.getAttribute('aria-expanded') === 'true') {
event.preventDefault();
const firstOption = dropdownSelect.querySelector("li > a");
if (firstOption) {
firstOption.focus();
}
} else {
openMenu(withFocus = true);
}
}
});

// Event listener for click events on dropdown button
dropdownButton.addEventListener("click", function (event) {
dropdown.addEventListener("click", function (event) {
event.stopPropagation();
if (dropdownButton.getAttribute('aria-expanded') === 'false') {
openMenu();
} else {
closeMenu();
}
dropdownSelect.classList.remove("tw-hidden");
});

// Event listener for keyboard events on dropdown container
dropdownSelect.addEventListener("keydown", function (event) {
if (event.key === 'Escape') {
closeMenu();
}
});


// Event listener for keyboard and click events on dropdown options
dropdownSelect.querySelectorAll("li").forEach(function (option) {
// Event listener for click events on dropdown options
option.querySelector("a")?.addEventListener("click", function (event) {
dropdownSelectItems.forEach((item) => {
item.addEventListener("click", function (event) {
event.stopPropagation();
closeMenu();
});

// Event listener for keyboard events on dropdown options
option.addEventListener("keydown", function (event) {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
option.querySelector("a").click();
closeMenu();
}

if (event.key === 'ArrowDown') {
event.preventDefault();
const nextOption = option?.nextElementSibling?.querySelector("a");
if (nextOption) {
nextOption.focus();
}
} else if (event.key === 'ArrowUp') {
event.preventDefault();
const prevOption = option?.previousElementSibling?.querySelector("a");
if (prevOption) {
prevOption.focus();
} else {
dropdownButton.focus();
}
}
dropdownSelect.classList.add("tw-hidden");
});
});
}
Expand Down

0 comments on commit d703343

Please sign in to comment.