1
0
mirror of https://github.com/twbs/bootstrap.git synced 2025-08-10 23:54:08 +02:00

Accessibility fixes to dynamic tabs (aria-selected, remove dynamic tabs with dropdowns)

* Use `aria-selected` instead of `aria-expanded`
* Change tab.js to use `aria-selected` rather than `aria-expanded`
* Add `aria-orientation=vertical` to vertical tab list
* Remove dynamic tabs with dropdowns
* Fix non-interactive code examples
* Only set `aria-selected` on the `role="tab"` trigger - this stops `aria-selected` being incorrectly added to the `role="tabpanel"` itself (probably harmless, but nonetheless incorrect)
This commit is contained in:
Patrick H. Lauke
2017-09-24 12:00:54 +02:00
committed by GitHub
parent d33b26d8c7
commit fd56ea370c
3 changed files with 79 additions and 121 deletions

View File

@@ -196,11 +196,15 @@ const Tab = (() => {
$(dropdownChild).removeClass(ClassName.ACTIVE)
}
active.setAttribute('aria-expanded', false)
if (active.getAttribute('role') === 'tab') {
active.setAttribute('aria-selected', false)
}
}
$(element).addClass(ClassName.ACTIVE)
element.setAttribute('aria-expanded', true)
if (element.getAttribute('role') === 'tab') {
element.setAttribute('aria-selected', true)
}
if (isTransitioning) {
Util.reflow(element)

View File

@@ -287,29 +287,29 @@ $(function () {
.bootstrapTab('show')
})
QUnit.test('selected tab should have aria-expanded', function (assert) {
QUnit.test('selected tab should have aria-selected', function (assert) {
assert.expect(8)
var tabsHTML = '<ul class="nav nav-tabs">'
+ '<li><a class="nav-item active" href="#home" toggle="tab" aria-expanded="true">Home</a></li>'
+ '<li><a class="nav-item" href="#profile" toggle="tab" aria-expanded="false">Profile</a></li>'
+ '<li><a class="nav-item active" href="#home" toggle="tab" aria-selected="true">Home</a></li>'
+ '<li><a class="nav-item" href="#profile" toggle="tab" aria-selected="false">Profile</a></li>'
+ '</ul>'
var $tabs = $(tabsHTML).appendTo('#qunit-fixture')
$tabs.find('li:first a').bootstrapTab('show')
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false')
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'shown tab has aria-selected = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'hidden tab has aria-selected = false')
$tabs.find('li:last a').trigger('click')
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'after click, shown tab has aria-expanded = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'after click, hidden tab has aria-expanded = false')
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'after click, shown tab has aria-selected = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'after click, hidden tab has aria-selected = false')
$tabs.find('li:first a').bootstrapTab('show')
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'shown tab has aria-expanded = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'hidden tab has aria-expanded = false')
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'shown tab has aria-selected = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'hidden tab has aria-selected = false')
$tabs.find('li:first a').trigger('click')
assert.strictEqual($tabs.find('.active').attr('aria-expanded'), 'true', 'after second show event, shown tab still has aria-expanded = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-expanded'), 'false', 'after second show event, hidden tab has aria-expanded = false')
assert.strictEqual($tabs.find('.active').attr('aria-selected'), 'true', 'after second show event, shown tab still has aria-selected = true')
assert.strictEqual($tabs.find('a:not(.active)').attr('aria-selected'), 'false', 'after second show event, hidden tab has aria-selected = false')
})
QUnit.test('selected tab should deactivate previous selected tab', function (assert) {
@@ -351,13 +351,13 @@ $(function () {
var tabsHTML =
'<nav class="nav nav-tabs" role="tablist">'
+ ' <a id="tab1" href="#x-tab1" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-tab1">Tab 1</a>'
+ ' <a href="#x-tab2" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab2" aria-expanded="true">Tab 2</a>'
+ ' <a href="#x-tab2" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab2" aria-selected="true">Tab 2</a>'
+ ' <a href="#x-tab3" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-tab3">Tab 3</a>'
+ '</nav>'
+ '<div class="tab-content">'
+ ' <div class="tab-pane" id="x-tab1" role="tabpanel">'
+ ' <nav class="nav nav-tabs" role="tablist">'
+ ' <a href="#nested-tab1" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab1" aria-expanded="true">Nested Tab 1</a>'
+ ' <a href="#nested-tab1" class="nav-item nav-link active" data-toggle="tab" role="tab" aria-controls="x-tab1" aria-selected="true">Nested Tab 1</a>'
+ ' <a id="tabNested2" href="#nested-tab2" class="nav-item nav-link" data-toggle="tab" role="tab" aria-controls="x-profile">Nested Tab2</a>'
+ ' </nav>'
+ ' <div class="tab-content">'