lp1828575 eg-grid options accessibility user/mrisher/lp1828575-eg-grid-options-accessibility-v2
authorMike Risher <mrisher@catalyte.io>
Fri, 18 Dec 2020 20:36:52 +0000 (20:36 +0000)
committerMike Risher <mrisher@catalyte.io>
Fri, 18 Dec 2020 20:46:54 +0000 (20:46 +0000)
Modify the options menu of eg-grid so that you can open it and use it
via the keyboard. Improve accessibility in general.

Signed-off-by: Mike Risher <mrisher@catalyte.io>
 Changes to be committed:
modified:   Open-ILS/src/eg2/src/app/share/grid/grid-column-config.component.html
modified:   Open-ILS/src/eg2/src/app/share/grid/grid-column-width.component.html
modified:   Open-ILS/src/eg2/src/app/share/grid/grid-header.component.html
modified:   Open-ILS/src/eg2/src/app/share/grid/grid-toolbar.component.html

Open-ILS/src/eg2/src/app/share/grid/grid-column-config.component.html
Open-ILS/src/eg2/src/app/share/grid/grid-column-width.component.html
Open-ILS/src/eg2/src/app/share/grid/grid-header.component.html
Open-ILS/src/eg2/src/app/share/grid/grid-toolbar.component.html

index 1bb80fa..8dd1487 100644 (file)
@@ -9,49 +9,54 @@
   <div class="modal-body eg-grid-column-config-dialog">
 
     <div class="row">
-      <div class="col-lg-1 eg-grid-header-cell" i18n>Visible</div>
-      <div class="col-lg-3 eg-grid-header-cell" i18n>Column Name</div>
-      <div class="col-lg-1 eg-grid-header-cell" i18n>Move Up</div>
-      <div class="col-lg-1 eg-grid-header-cell" i18n>Move Down</div>
-      <div class="col-lg-2 eg-grid-header-cell" i18n>First Visible</div>
-      <div class="col-lg-2 eg-grid-header-cell" i18n>Last Visible</div>
-      <div class="col-lg-2 eg-grid-header-cell" 
-        *ngIf="columnSet.isMultiSortable" i18n>Sort Priority</div>
+      <div class="col-lg-1 eg-grid-header-cell" i18n id="colVisible">Visible</div>
+      <div class="col-lg-3 eg-grid-header-cell" i18n id="mngColNameHeader">Column Name</div>
+      <div class="col-lg-1 eg-grid-header-cell" i18n id="moveUp">Move Up</div>
+      <div class="col-lg-1 eg-grid-header-cell" i18n id="moveDown">Move Down</div>
+      <div class="col-lg-2 eg-grid-header-cell" i18n id="firstVisible">First Visible</div>
+      <div class="col-lg-2 eg-grid-header-cell" i18n id="lastVisible">Last Visible</div>
+      <div class="col-lg-2 eg-grid-header-cell" i18n id="sortPriority"
+         *ngIf="columnSet.isMultiSortable">Sort Priority</div>
     </div>
-    <div class="row pt-1" *ngFor="let col of columnSet.columns"
+    <div class="row pt-1" *ngFor="let col of columnSet.columns; index as manageColIndex"
       [ngClass]="{visible : col.visible}">
-      <div class="col-lg-1" (click)="col.visible=!col.visible">
-        <span *ngIf="col.visible" class="badge badge-success">&#x2713;</span>
-        <span *ngIf="!col.visible" class="badge badge-warning">&#x2717;</span>
+      <div class="col-lg-1">
+        <button *ngIf="col.visible" (click)="col.visible=!col.visible"
+          role="checkbox" aria-checked="true"
+          attr.aria-labelledby="mngColName-{{manageColIndex}} colVisible"
+          class="badge badge-success">&#x2713;</button>
+        <button *ngIf="!col.visible" (click)="col.visible=!col.visible" 
+          role="checkbox" aria-checked="false"
+          attr.aria-labelledby="mngColName-{{manageColIndex}} colVisible"
+          class="badge badge-warning">&#x2717;</button>
       </div>
-      <div class="col-lg-3" (click)="col.visible=!col.visible">{{col.label}}</div>
+      <div class="col-lg-3" (click)="col.visible=!col.visible" role="button"
+        attr.aria-labelledby="mngColName-{{manageColIndex}} mngColNameHeader"
+        tabindex="0">{{col.label}}</div>
       <div class="col-lg-1">
-        <a class="no-href" title="Move column up" i18n-title
-          (click)="columnSet.moveColumn(col, -1)">
-          <span class="material-icons">arrow_upward</span>
-        </a>
+        <button (click)="columnSet.moveColumn(col, -1)" class="btn material-icons"
+          attr.aria-labelledby="mngColName-{{manageColIndex}} moveUp"
+          title="Move column up" i18n-title>arrow_upward</button>
       </div>
       <div class="col-lg-1">
-        <a class="no-href" title="Move column down" i18n-title
-          (click)="columnSet.moveColumn(col, 1)">
-          <span class="material-icons">arrow_downward</span>
-        </a>
+        <button (click)="columnSet.moveColumn(col, 1)" class="btn material-icons"
+          attr.aria-labelledby="mngColName-{{manageColIndex}} moveDown"
+          title="Move column down" i18n-title>arrow_downward</button>
       </div>
       <div class="col-lg-2">
-        <a class="no-href" title="Make first visible" i18n-title
-          (click)="columnSet.moveColumn(col, -10000)">
-          <span class="material-icons">vertical_align_top</span>
-        </a>
+          <button (click)="columnSet.moveColumn(col, -10000)" class="btn material-icons"
+            attr.aria-labelledby="mngColName-{{manageColIndex}} firstVisible"
+            title="Make first visible" i18n-title>vertical_align_top</button>
       </div>
       <div class="col-lg-2">
-        <a class="no-href" title="Make last visible" i18n-title
-          (click)="columnSet.moveColumn(col, 10000)">
-          <span class="material-icons">vertical_align_bottom</span>
-        </a>
+          <button (click)="columnSet.moveColumn(col, 10000)" class="btn material-icons"
+            attr.aria-labelledby="mngColName-{{manageColIndex}} lastVisible"
+            title="Make last visible" i18n-title>vertical_align_bottom</button>
       </div>
       <div class="col-lg-2" *ngIf="columnSet.isMultiSortable">
         <div *ngIf="col.isMultiSortable">
           <input type='number' [(ngModel)]="col.sort"
+            attr.aria-labelledby="mngColName-{{manageColIndex}} sortPriority"
             title="Sort Priority / Direction" i18n-title style='width:2.8em'/>
         </div>
       </div>
index ca24c00..3821df7 100644 (file)
@@ -1,20 +1,20 @@
 <div *ngIf="isVisible" class="eg-grid-column-width-config">
   <div class="eg-grid-row">
-    <div class="eg-grid-column-width-header" i18n>Expand</div>
-    <div *ngFor="let col of columnSet.displayColumns()
+    <div class="eg-grid-column-width-header" i18n id="expandCol">Expand</div>
+    <div *ngFor="let col of columnSet.displayColumns(); index as gridHeaderColExpandIndex"
       class="eg-grid-cell text-center" [ngStyle]="{flex:col.flex}">
-      <a (click)="expandColumn(col)" title="Expand Column" i18n-title>
-        <span class="material-icons eg-grid-column-width-icon">call_made</span>
-      </a>
+      <button (click)="expandColumn(col)" class="btn material-icons eg-grid-column-width-icon"
+        attr.aria-labelledby="expandCol gridHeaderCol-{{gridHeaderColExpandIndex}}"
+        title="Expand Column" i18n-title>call_made</button>
     </div>
   </div>
   <div class="eg-grid-row">
-    <div class="eg-grid-column-width-header" i18n>Shrink</div>
-    <div *ngFor="let col of columnSet.displayColumns()
+    <div class="eg-grid-column-width-header" i18n id="shrinkCol">Shrink</div>
+    <div *ngFor="let col of columnSet.displayColumns(); index as gridHeaderColShrinkIndex"
       class="eg-grid-cell text-center" [ngStyle]="{flex:col.flex}">
-      <a (click)="shrinkColumn(col)" title="Shrink Column" i18n-title>
-        <span class="material-icons eg-grid-column-width-icon">call_received</span>
-      </a>
+      <button (click)="shrinkColumn(col)" class="btn material-icons eg-grid-column-width-icon"
+        attr.aria-labelledby="shrinkCol gridHeaderCol-{{gridHeaderColShrinkIndex}}"
+        title="Shrink Column" i18n-title>call_received</button>
     </div>
   </div>
 </div>
index a680765..ebbf5cc 100644 (file)
@@ -18,7 +18,7 @@
     <span class="material-icons">notifications</span>
   </div>
   <div role="columnheader"
-    *ngFor="let col of context.columnSet.displayColumns()"
+    *ngFor="let col of context.columnSet.displayColumns(); index as gridHeaderColIndex"
     draggable="true"
     (dragstart)="dragColumn = col"
     (drop)="onColumnDrop(col)"
@@ -28,7 +28,8 @@
     class="eg-grid-cell eg-grid-header-cell" [ngStyle]="{flex:col.flex}">
     <a class="sortable label-with-material-icon" *ngIf="col.isSortable"
       (click)="sortOneColumn(col)">
-      <span class="eg-grid-header-cell-sort-label">{{col.label}}</span>
+      <span class="eg-grid-header-cell-sort-label" 
+        id="gridHeaderCol-{{gridHeaderColIndex}}">{{col.label}}</span>
       <span class="material-icons eg-grid-header-cell-sort-arrow"
         *ngIf="isColumnSorting(col, 'ASC')">arrow_upwards</span>
       <span class="material-icons eg-grid-header-cell-sort-arrow"
index eb701ce..bea4a5b 100644 (file)
       </span>
     </button>
     <div class="dropdown-menu" ngbDropdownMenu>
-      <a class="dropdown-item"
-        *ngFor="let count of [5, 10, 25, 50, 100]"
-        (click)="gridContext.pager.setLimit(count)">
-        <span class="ml-2">{{count}}</span>
-      </a>
+      <div class="dropdown-item"
+        *ngFor="let count of [5, 10, 25, 50, 100]">
+        <button ngbDropdownItem (click)="gridContext.pager.setLimit(count)" class="ml-2">{{count}}</button>
+      </div>
     </div>
   </div>
   
       <span title="Show Grid Options" i18n-title
         class="material-icons mat-icon-in-button">settings</span>
     </button>
-    <div class="dropdown-menu scrollable-menu" ngbDropdownMenu>
-      <a class="dropdown-item label-with-material-icon"
-        (click)="columnConfDialog.open({size:'lg'})">
-        <span class="material-icons">build</span>
-        <span class="ml-2" i18n>Manage Columns</span>
-      </a>
-      <a class="dropdown-item label-with-material-icon"
+    <div style="cursor: pointer" class="dropdown-menu scrollable-menu" ngbDropdownMenu>
+      <div class="dropdown-item label-with-material-icon" (click)="columnConfDialog.open({size:'lg'})">
+          <button aria-labelledby="manage" class="btn px-0 material-icons">build</button>
+          <span id="manage" i18n class="ml-2">Manage Columns</span>
+      </div>
+      <div class="dropdown-item label-with-material-icon"
         (click)="colWidthConfig.isVisible = !colWidthConfig.isVisible">
-        <span class="material-icons">compare_arrows</span>
-        <span class="ml-2" i18n>Manage Column Widths</span>
-      </a>
-      <a class="dropdown-item label-with-material-icon"
+        <button aria-labelledby="widths" class="btn px-0 material-icons">compare_arrows</button>
+        <span id="widths" class="ml-2" i18n>Manage Column Widths</span>
+      </div>
+      <div class="dropdown-item label-with-material-icon"
         *ngIf="!disableSaveSettings"
         (click)="saveGridConfig()">
-        <span class="material-icons">save</span>
-        <span class="ml-2" i18n>Save Grid Settings</span>
-      </a>
-      <a class="dropdown-item label-with-material-icon"
+        <button aria-labelledby="saveGrid" class="btn px-0 material-icons">save</button>
+        <span id="saveGrid" class="ml-2" i18n>Save Grid Settings</span>
+      </div>
+      <div class="dropdown-item label-with-material-icon"
         (click)="gridContext.columnSet.reset()">
-        <span class="material-icons">restore</span>
-        <span class="ml-2" i18n>Reset Columns</span>
-      </a>
+        <button aria-labelledby="reset" class="btn px-0 material-icons">restore</button>
+        <span id="reset" class="ml-2" i18n>Reset Columns</span>
+      </div>
       <a class="dropdown-item label-with-material-icon"
-        (click)="generateCsvExportUrl($event)"
-        [download]="csvExportFileName"
-        [href]="csvExportUrl">
-        <span class="material-icons">cloud_download</span>
-        <span class="ml-2" i18n>Download Full CSV</span>
-      </a>
-      <a class="dropdown-item label-with-material-icon" (click)="printHtml()">
-        <span class="material-icons">print</span>
-        <span class="ml-2" i18n>Print Full Grid</span>
+        (click)="generateCsvExportUrl($event)" [download]="csvExportFileName"
+        [href]="csvExportUrl" aria-labelledby="download">
+        <div class="btn px-0 material-icons">cloud_download</div>
+        <span id="download" class="ml-2" i18n>Download Full CSV</span>
       </a>
+      <div class="dropdown-item label-with-material-icon" (click)="printHtml()">
+        <button aria-labelledby="print" class="btn px-0 material-icons">print</button>
+        <span id="print" class="ml-2" i18n>Print Full Grid</span>
+      </div>
 
       <div class="dropdown-divider"></div>
-
-      <a class="dropdown-item label-with-material-icon"
-        (click)="col.visible=!col.visible" *ngFor="let col of gridContext.columnSet.columns">
-        <span *ngIf="col.visible" class="badge badge-success">&#x2713;</span>
-        <span *ngIf="!col.visible" class="badge badge-warning">&#x2717;</span>
-        <span class="ml-2">{{col.label}}</span>
-      </a>
+      <div class="dropdown-item label-with-material-icon"
+        *ngFor="let col of gridContext.columnSet.columns; index as visIndex" 
+        (click)="col.visible=!col.visible">
+        <button attr.aria-labelledby="visCheck-{{visIndex}}"
+          *ngIf="col.visible" class="badge badge-success" tabindex="0">&#x2713;</button>
+        <button attr.aria-labelledby="visCheck-{{visIndex}}"
+          *ngIf="!col.visible" class="badge badge-warning" tabindex="0">&#x2717;</button>
+        <span id="visCheck-{{visIndex}}" class="ml-2">{{col.label}}</span>
+      </div>
 
     </div>
   </div>