Skip to content

Replace JavaScript-based dropdowns with CSS-only dropdowns #18339

Open
@miketheman

Description

@miketheman

There's a JavaScript function that handles the interactive nature of clicky dropdowns:

let bindDropdowns = function () {
// Bind click handlers to dropdowns for keyboard users
let dropdowns = document.querySelectorAll(".dropdown");
for (let dropdown of dropdowns) {
let trigger = dropdown.querySelector(".dropdown__trigger");
let content = dropdown.querySelector(".dropdown__content");
let openDropdown = function () {
content.classList.add("display-block");
content.removeAttribute("aria-hidden");
trigger.setAttribute("aria-expanded", "true");
};
let closeDropdown = function () {
content.classList.remove("display-block");
content.setAttribute("aria-hidden", "true");
trigger.setAttribute("aria-expanded", "false");
};
if (!trigger.dataset.dropdownBound) {
// If the user has clicked the trigger (either with a mouse or by
// pressing space/enter on the keyboard) show the content
trigger.addEventListener("click", function () {
if (content.classList.contains("display-block")) {
closeDropdown();
} else {
openDropdown();
}
});
// Close the dropdown when a user moves away with their mouse or keyboard
let closeInactiveDropdown = function (event) {
if (dropdown.contains(event.relatedTarget)) {
return;
}
closeDropdown();
};
dropdown.addEventListener("focusout", closeInactiveDropdown, false);
dropdown.addEventListener("mouseout", closeInactiveDropdown, false);
// Close the dropdown if the user presses the escape key
document.addEventListener("keydown", function(event) {
if (event.key === "Escape") {
closeDropdown();
}
});
// Set the 'data-dropdownBound' attribute so we don't bind multiple
// handlers to the same trigger after the client-side-includes load
trigger.dataset.dropdownBound = true;
}
}
};
// Bind the dropdowns when the page is ready
docReady(bindDropdowns);

Related CSS: https://github.com/pypi/warehouse/blob/f59df186dc62274b5831a72f639a1e92bbe3f94c/warehouse/static/sass/blocks/_dropdown.scss#L1-L0

There are 5 main pages that reference a dropdown:

  • warehouse/templates/base.html
  • warehouse/templates/manage/account.html
  • warehouse/templates/manage/unverified-account.html
  • warehouse/templates/manage/project/release.html
  • warehouse/templates/includes/current-user-indicator.html (NOTE: this one needs access to a cookie, so might not be able to completely remove JavaScript for this, maybe only the dropdown behaviors)

There's a bunch of content out there on how to use CSS-only dropdowns, here's some links I found interesting:

Metadata

Metadata

Assignees

No one assigned

    Labels

    CSS/SCSSrequires change to CSS/SCSS filesHTMLrequires change to HTML files

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions