summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Carrick <tom@carrick.eu>2020-05-16 14:16:56 +0200
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-05-28 11:20:39 +0200
commitdc3234be48d17def4e951d678c0ec39c5ff94830 (patch)
treee193ce3c59dc14785e24f707a8950b5eb581a844
parent15fc360b91f339d926c6f321c8d5c105dba80756 (diff)
[3.1.x] Refs #31034 -- Improved accessibility of admin navigation sidebar.
Backport of 780473d75625d014cbe9b0acdea40b7a5970d5d8 from master
-rw-r--r--django/contrib/admin/static/admin/css/nav_sidebar.css1
-rw-r--r--django/contrib/admin/static/admin/js/nav_sidebar.js17
-rw-r--r--django/contrib/admin/templates/admin/nav_sidebar.html3
-rw-r--r--tests/admin_views/test_nav_sidebar.py12
4 files changed, 32 insertions, 1 deletions
diff --git a/django/contrib/admin/static/admin/css/nav_sidebar.css b/django/contrib/admin/static/admin/css/nav_sidebar.css
index 6fcfb26131..7d4c75fe12 100644
--- a/django/contrib/admin/static/admin/css/nav_sidebar.css
+++ b/django/contrib/admin/static/admin/css/nav_sidebar.css
@@ -17,6 +17,7 @@
cursor: pointer;
font-size: 20px;
color: #447e9b;
+ padding: 0;
}
[dir="rtl"] .toggle-nav-sidebar {
diff --git a/django/contrib/admin/static/admin/js/nav_sidebar.js b/django/contrib/admin/static/admin/js/nav_sidebar.js
index 70685f2c06..efaa7214b8 100644
--- a/django/contrib/admin/static/admin/js/nav_sidebar.js
+++ b/django/contrib/admin/static/admin/js/nav_sidebar.js
@@ -2,18 +2,35 @@
{
const toggleNavSidebar = document.getElementById('toggle-nav-sidebar');
if (toggleNavSidebar !== null) {
+ const navLinks = document.querySelectorAll('#nav-sidebar a');
+ function disableNavLinkTabbing() {
+ for (const navLink of navLinks) {
+ navLink.tabIndex = -1;
+ }
+ }
+ function enableNavLinkTabbing() {
+ for (const navLink of navLinks) {
+ navLink.tabIndex = 0;
+ }
+ }
+
const main = document.getElementById('main');
let navSidebarIsOpen = localStorage.getItem('django.admin.navSidebarIsOpen');
if (navSidebarIsOpen === null) {
navSidebarIsOpen = 'true';
}
+ if (navSidebarIsOpen === 'false') {
+ disableNavLinkTabbing();
+ }
main.classList.toggle('shifted', navSidebarIsOpen === 'true');
toggleNavSidebar.addEventListener('click', function() {
if (navSidebarIsOpen === 'true') {
navSidebarIsOpen = 'false';
+ disableNavLinkTabbing();
} else {
navSidebarIsOpen = 'true';
+ enableNavLinkTabbing();
}
localStorage.setItem('django.admin.navSidebarIsOpen', navSidebarIsOpen);
main.classList.toggle('shifted');
diff --git a/django/contrib/admin/templates/admin/nav_sidebar.html b/django/contrib/admin/templates/admin/nav_sidebar.html
index 84956c1bd1..9fde4c28e1 100644
--- a/django/contrib/admin/templates/admin/nav_sidebar.html
+++ b/django/contrib/admin/templates/admin/nav_sidebar.html
@@ -1,4 +1,5 @@
-<div class="sticky toggle-nav-sidebar" id="toggle-nav-sidebar"></div>
+{% load i18n %}
+<button class="sticky toggle-nav-sidebar" id="toggle-nav-sidebar" aria-label="{% translate 'Toggle navigation' %}"></button>
<nav class="sticky" id="nav-sidebar">
{% include 'admin/app_list.html' with app_list=available_apps %}
</nav>
diff --git a/tests/admin_views/test_nav_sidebar.py b/tests/admin_views/test_nav_sidebar.py
index 9d52c541c0..01cd4cfee7 100644
--- a/tests/admin_views/test_nav_sidebar.py
+++ b/tests/admin_views/test_nav_sidebar.py
@@ -97,7 +97,14 @@ class SeleniumTests(AdminSeleniumTestCase):
def test_sidebar_can_be_closed(self):
self.selenium.get(self.live_server_url + reverse('test_with_sidebar:auth_user_changelist'))
toggle_button = self.selenium.find_element_by_css_selector('#toggle-nav-sidebar')
+ self.assertEqual(toggle_button.tag_name, 'button')
+ self.assertEqual(toggle_button.get_attribute('aria-label'), 'Toggle navigation')
+ for link in self.selenium.find_elements_by_css_selector('#nav-sidebar a'):
+ self.assertEqual(link.get_attribute('tabIndex'), '0')
toggle_button.click()
+ # Hidden sidebar is not reachable via keyboard navigation.
+ for link in self.selenium.find_elements_by_css_selector('#nav-sidebar a'):
+ self.assertEqual(link.get_attribute('tabIndex'), '-1')
main_element = self.selenium.find_element_by_css_selector('#main')
self.assertNotIn('shifted', main_element.get_attribute('class').split())
@@ -115,7 +122,12 @@ class SeleniumTests(AdminSeleniumTestCase):
self.assertNotIn('shifted', main_element.get_attribute('class').split())
toggle_button = self.selenium.find_element_by_css_selector('#toggle-nav-sidebar')
+ # Hidden sidebar is not reachable via keyboard navigation.
+ for link in self.selenium.find_elements_by_css_selector('#nav-sidebar a'):
+ self.assertEqual(link.get_attribute('tabIndex'), '-1')
toggle_button.click()
+ for link in self.selenium.find_elements_by_css_selector('#nav-sidebar a'):
+ self.assertEqual(link.get_attribute('tabIndex'), '0')
self.assertEqual(
self.selenium.execute_script("return localStorage.getItem('django.admin.navSidebarIsOpen')"),
'true',