Skip to content

Commit

Permalink
[Accessibility] Give kuiTables keyboard-accessible column headers (#1…
Browse files Browse the repository at this point in the history
…3586) (#13692)

* Make KuiTable headers keyboard-accessible in UI Framework.
* Use flexbox to consistently apply spacing between table header cell text and sort icon.
* Add aria-label attributes to KuiTableHeaderCell, KuiTableHeaderCheckBoxCell, and KuiTableRowCheckBoxCell.
* Update Jest snapshots.
* Update Dashboard listing table with new markup.
* Update Saved Objects tables with new markup.
* Update Settings table with new markup.
* Update Visualize listing table with new markup.
* Remove padding-right for cells containing checkboxes.
* Update sortableColumn directive with new markup.
  • Loading branch information
cjcenizal authored Aug 24, 2017
1 parent f8f25d9 commit 592253f
Show file tree
Hide file tree
Showing 22 changed files with 628 additions and 599 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,72 +125,90 @@
<!-- Table -->
<table class="kuiTable" ng-if="listingController.items.length">
<thead>
<tr>
<th class="kuiTableHeaderCell kuiTableHeaderCell--checkBox" ng-if="!listingController.hideWriteControls">
<input
type="checkbox"
class="kuiCheckBox"
ng-checked="listingController.areAllItemsChecked()"
ng-click="listingController.toggleAll()"
>
</th>

<th class="kuiTableHeaderCell" ng-click="listingController.sortOn('title')">
Name
<span
class="kuiIcon"
ng-show="listingController.getSortedProperty().name == 'title'"
ng-class="listingController.isAscending('title') ? 'fa-caret-up' : 'fa-caret-down'"
>
</span>
</th>
<th class="kuiTableHeaderCell" ng-click="listingController.sortOn('description')">
Description
<span
class="kuiIcon"
ng-show="listingController.getSortedProperty().name == 'description'"
ng-class="listingController.isAscending('description') ? 'fa-caret-up' : 'fa-caret-down'"
>
</span>
</th>
</tr>
</thead>
<tr>
<th class="kuiTableHeaderCell kuiTableHeaderCell--checkBox" ng-if="!listingController.hideWriteControls">
<div class="kuiTableHeaderCell__liner">
<input
type="checkbox"
class="kuiCheckBox"
ng-checked="listingController.areAllItemsChecked()"
ng-click="listingController.toggleAll()"
aria-label="{{listingController.areAllItemsChecked() ? 'Deselect all rows' : 'Select all rows'}}"
>
</div>
</th>

<tbody>
<tr
ng-repeat="item in listingController.pageOfItems track by item.id"
class="kuiTableRow"
>
<td class="kuiTableRowCell kuiTableRowCell--checkBox" ng-if="!listingController.hideWriteControls">
<div class="kuiTableRowCell__liner">
<input
type="checkbox"
class="kuiCheckBox"
data-test-subj="dashboardListItemCheckbox"
ng-click="listingController.toggleItem(item)"
ng-checked="listingController.isItemChecked(item)"
<th class="kuiTableHeaderCell">
<button
class="kuiTableHeaderCellButton"
ng-class="{'kuiTableHeaderCellButton-isSorted': listingController.getSortedProperty().name == 'title'}"
ng-click="listingController.sortOn('title')"
aria-label="{{listingController.isAscending('title') ? 'Sort name descending' : 'Sort name ascending'}}"
>
</div>
</td>
<span class="kuiTableHeaderCell__liner">
Name
<span
class="kuiTableSortIcon kuiIcon"
ng-class="listingController.isAscending('title') ? 'fa-long-arrow-up' : 'fa-long-arrow-down'"
></span>
</span>
</button>
</th>

<td class="kuiTableRowCell">
<div class="kuiTableRowCell__liner">
<a
class="kuiLink"
data-test-subj="dashboardListingTitleLink"
ng-href="{{ listingController.getUrlForItem(item) }}"
<th class="kuiTableHeaderCell">
<button
class="kuiTableHeaderCellButton"
ng-class="{'kuiTableHeaderCellButton-isSorted': listingController.getSortedProperty().name == 'description'}"
ng-click="listingController.sortOn('description')"
aria-label="{{listingController.isAscending('description') ? 'Sort description descending' : 'Sort description ascending'}}"
>
{{ item.title }}
</a>
</div>
</td>
<td class="kuiTableRowCell kuiTableRowCell--wrap">
<div class="kuiTableRowCell__liner">
{{ item.description }}
</div>
</td>
</tr>
<span class="kuiTableHeaderCell__liner">
Description
<span
class="kuiTableSortIcon kuiIcon"
ng-class="listingController.isAscending('description') ? 'fa-long-arrow-up' : 'fa-long-arrow-down'"
></span>
</span>
</button>
</th>
</tr>
</thead>

<tbody>
<tr
ng-repeat="item in listingController.pageOfItems track by item.id"
class="kuiTableRow"
>
<td class="kuiTableRowCell kuiTableRowCell--checkBox" ng-if="!listingController.hideWriteControls">
<div class="kuiTableRowCell__liner">
<input
type="checkbox"
class="kuiCheckBox"
data-test-subj="dashboardListItemCheckbox"
ng-click="listingController.toggleItem(item)"
ng-checked="listingController.isItemChecked(item)"
aria-label="{{listingController.isItemChecked(item) ? 'Deselect row' : 'Select row'}}"
>
</div>
</td>

<td class="kuiTableRowCell">
<div class="kuiTableRowCell__liner">
<a
class="kuiLink"
data-test-subj="dashboardListingTitleLink"
ng-href="{{ listingController.getUrlForItem(item) }}"
>
{{ item.title }}
</a>
</div>
</td>
<td class="kuiTableRowCell kuiTableRowCell--wrap">
<div class="kuiTableRowCell__liner">
{{ item.description }}
</div>
</td>
</tr>
</tbody>
</table>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,16 +130,22 @@ <h1 class="kuiTitle">
<thead>
<tr>
<th class="kuiTableHeaderCell kuiTableHeaderCell--checkBox">
<input
type="checkbox"
aria-label="Select All"
class="kuiCheckBox"
ng-checked="managementObjectsController.areAllRowsChecked()"
ng-click="toggleAll()"
>
<div class="kuiTableHeaderCell__liner">
<input
type="checkbox"
aria-label="Select All"
class="kuiCheckBox"
ng-checked="managementObjectsController.areAllRowsChecked()"
ng-click="toggleAll()"
aria-label="{{managementObjectsController.areAllRowsChecked() ? 'Deselect all rows' : 'Select all rows'}}"
>
</div>
</th>

<th class="kuiTableHeaderCell">
Title
<div class="kuiTableHeaderCell__liner">
Title
</div>
</th>
</tr>
</thead>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,22 @@
<thead>
<tr>
<th class="kuiTableHeaderCell">
Name
<div class="kuiTableRowCell__liner">
Name
</div>
</th>
<th class="kuiTableHeaderCell">
Value
<div class="kuiTableRowCell__liner">
Value
</div>
</th>
<th
class="kuiTableHeaderCell kuiTableHeaderCell--alignRight"
style="width: 180px"
>
<!-- Actions -->
<div class="kuiTableRowCell__liner">
<!-- Actions -->
</div>
</th>
</tr>
</thead>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,36 +113,53 @@
<thead>
<tr>
<th class="kuiTableHeaderCell kuiTableHeaderCell--checkBox">
<input
type="checkbox"
class="kuiCheckBox"
ng-checked="listingController.areAllItemsChecked()"
ng-click="listingController.toggleAll()"
>
<div class="kuiTableHeaderCell__liner">
<input
type="checkbox"
class="kuiCheckBox"
ng-checked="listingController.areAllItemsChecked()"
ng-click="listingController.toggleAll()"
aria-label="{{listingController.areAllItemsChecked() ? 'Deselect all rows' : 'Select all rows'}}"
>
</div>
</th>

<th
class="kuiTableHeaderCell"
ng-click="listingController.sortOn('title')"
>
Name
<span
class="kuiIcon"
ng-show="listingController.getSortedProperty().name === 'title'"
ng-class="listingController.isAscending('title') ? 'fa-caret-up' : 'fa-caret-down'"
></span>
<button
class="kuiTableHeaderCellButton"
ng-class="{'kuiTableHeaderCellButton-isSorted': listingController.getSortedProperty().name == 'title'}"
ng-click="listingController.sortOn('title')"
aria-label="{{listingController.isAscending('title') ? 'Sort name descending' : 'Sort name ascending'}}"
>
<span class="kuiTableHeaderCell__liner">
Name
<span
class="kuiTableSortIcon kuiIcon"
ng-class="listingController.isAscending('title') ? 'fa-long-arrow-up' : 'fa-long-arrow-down'"
></span>
</span>
</button>
</th>

<th
class="kuiTableHeaderCell"
ng-click="listingController.sortOn('type')"
>
Type
<span
class="kuiIcon"
ng-show="listingController.getSortedProperty().name === 'type'"
ng-class="listingController.isAscending('type') ? 'fa-caret-up' : 'fa-caret-down'"
></span>
<button
class="kuiTableHeaderCellButton"
ng-class="{'kuiTableHeaderCellButton-isSorted': listingController.getSortedProperty().name == 'type'}"
ng-click="listingController.sortOn('type')"
aria-label="{{listingController.isAscending('type') ? 'Sort type descending' : 'Sort type ascending'}}"
>
<span class="kuiTableHeaderCell__liner">
Type
<span
class="kuiTableSortIcon kuiIcon"
ng-class="listingController.isAscending('type') ? 'fa-long-arrow-up' : 'fa-long-arrow-down'"
></span>
</span>
</button>
</th>
</tr>
</thead>
Expand All @@ -159,6 +176,7 @@
class="kuiCheckBox"
ng-click="listingController.toggleItem(item)"
ng-checked="listingController.isItemChecked(item)"
aria-label="{{listingController.isItemChecked(item) ? 'Deselect row' : 'Select row'}}"
>
</div>
</td>
Expand Down
28 changes: 14 additions & 14 deletions src/ui/public/sortable_column/sortable_column.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<div ng-click="sortableColumn.toggle()">
<div
class="kuiTableHeaderCell__liner"
ng-transclude
></div>
<span
class="kuiTableSortIcon kuiIcon fa-long-arrow-up"
ng-show="sortableColumn.isSortedAscending()"
></span>
<span
class="kuiTableSortIcon kuiIcon fa-long-arrow-down"
ng-show="sortableColumn.isSortedDescending()"
></span>
</div>
<button
class="kuiTableHeaderCellButton"
ng-class="{'kuiTableHeaderCellButton-isSorted': sortableColumn.isSorted()}"
ng-click="sortableColumn.toggle()"
aria-label="{{sortableColumn.getAriaLabel()}}"
>
<span class="kuiTableHeaderCell__liner">
<span ng-transclude></span>
<span
class="kuiTableSortIcon kuiIcon"
ng-class="sortableColumn.isSortedAscending() ? 'fa-long-arrow-up' : 'fa-long-arrow-down'"
></span>
</span>
</button>
13 changes: 11 additions & 2 deletions src/ui/public/sortable_column/sortable_column.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,21 @@ app.directive('sortableColumn', function () {
}
}

getAriaLabel() {
const direction = this.isSortedAscending() ? 'descending' : 'ascending';
return `Sort ${this.field} ${direction}`;
}

isSorted() {
return this.sortField === this.field;
}

isSortedAscending() {
return (this.sortField === this.field) && (!this.sortReverse);
return this.isSorted() && !this.sortReverse;
}

isSortedDescending() {
return (this.sortField === this.field) && (this.sortReverse);
return this.isSorted() && this.sortReverse;
}
}
};
Expand Down
Loading

0 comments on commit 592253f

Please sign in to comment.