Improving Usability, Accessibility and ARIA Compliance with Grid Keyboard Navigation

Zdravko Kolev / Tuesday, June 02, 2020

As user expectations evolve, modern web applications have grown more and more complex. They define user interface patterns like virtualized scrolling of content, complex data tables with editable cells, and different overlay components, just to name a few. That is not a problem for users leveraging a mouse or touchpad, as they can easily navigate through the page elements and interact with them. But for those using a keyboard, this can dramatically impact their user experience. The number of controls and items on most web pages has increased dramatically – meaning that a modern web page may contain hundreds of tab stops. 

At Infragistics, we want to ensure an optimal user experience, regardless of whether you are using a mouse, a touchpad or just a keyboard. That is why we have created a new user interface pattern for keyboard navigation within a page, called Active element navigation. This pattern reduces the number of tab stops within the interface designed for the igxGrid to only five, and exposes plenty of new keyboard shortcuts for efficiency. Each tab stop element has a single-entry point, and from there users can easily navigate to different items in the corresponding grid element container by simply using the arrow keys. Thus, simplifying navigation and improving usability.

Header navigation example

Page Tab Sequence and ARIA Support 

As described in the Fundamental Keyboard Navigation Conventions section of W3C’s WAI-ARIA Authoring Practices 1.1, the tab sequence should include only one focusable element of a Composite UI Component  and we have five such Composite UI Components, hence five tab stops: 

  • Toolbar/Group by Area, if existing
  • Header row container - The first cell of the header row will become active
  • Tbody - The first igxCell (0,0) of the body container will become active
  • Footer - The first cell in the Column Summary will become active (if summaries are enabled) 
  • Pager UI - Items per page drop-down will become active

Pressing the Tab key will move focus out of the current container to the next element in the tab sequence - This is illustrated with the image below with the tab sequence "Grid Toolbar" -> "Grid Headers" -> "Grid Body Container" -> "Summaries" -> "Footer - Grid Paginator". 

Page Tab Stops

Each of the five tab-stop containers can be considered as separate grouping entity, reducing the number of tab stops on the page. The Grid has a rich DOM structure, along with plenty of virtualized containers, which allows for greater performanceTherefore, we have more than one focusable Grid element part of the page tab sequence and allows us to have separate and rich navigation on all tab stop containers 

Note: Keep in mind that the default-browser-focusable actions are persisted. We are not preventing focus of the HTML element part of ng-templates or other elements added separately in the Grid. The browser will handle its focus actions by default - there is no need to apply additional focusable directives. 

Active Element Navigation

Referring back to W3c’s Fundamental Keyboard Navigation Conventions, all interactive UI components need to be accessible via a keyboard. This is best achieved by either including them in the tab sequence or by making them reachable from a component that is in the tab sequence. In the Grid's case navigation, it is possible to move through each one of these focusable containers with the navigation keys (Arrow keys, home/end, ctrl + 'action key') and this is where the Active element navigation concept kicks inActive element is the first visible element from the focused container. BUT this element does not become focused - the focus remains on the actual container. The active element gives you the ability to navigate through most of the Grid elements, and activate features based on the focused Composite component. 

How Do Focused Elements Differ with Selected and Active Elements?  

We consider the focused element as a pointer - it tracks the path of navigation (page tab sequence). As we already know, we have five such composite elements. The `Active element` is used to navigate through these focusable containers. As you can see in the image belowfor visual users, the thick orange border with the gray cell background indicates the current active element. 

Selected elements are elements that have aria-selected="true". In the igxGrid case, aria-selected is applicable to all three types of selection elements cell, row and column selection (WAI-ARIA

In conclusion 

  • Focused element - tracking the path of page tab sequence - Grid's toolbar, header, body, footer, and pager
  • Active element - navigates within the five focusable containers with the arrow keys (and special keys like home/end) 
  • Selected element - having aria-selected="true" along with Grid selection styles applied (cell, row or column selection) 

We follow the guidelines within the WAI-ARIA Authoring Practices Guide, for specific recommendations on key and behavior mapping. So, the roles that ARIA Grid provides are recognizable in the igxGrid as well: grid, row, grid cell, row header, and column header.  

Tab navigation  

The grid follows the primary keyboard navigation convention that thetab and shift + tab keys move the focus from one UI component to another. The arrow keys change the active state inside of components that include multiple elements.  

Compared to previous tab interaction behavior, we've changed the following: 

  • You cannot use tab key to navigate between the cells in the IgxGrid. The navigation is now performed only with arrow keys. 
  • With the tab key you can only navigate to the next editable cell (Only when the cell is in edit mode). When the last editable cell (of the row) is reached, the navigation will continue to next row's editable cell. If the last editable cell is reached, the tab navigation will continue to the next focusable tab stop element. 

Performance improvements and code enhancements  

As a result of the new keyboard navigation conceptwhave been able to optimize our code and implement performance improvements, such as: 

  • Cell focus and blur handlers have been removed 
  • Wheel and view detach handlers have been removed as well. 
  • Reduced navigation services. We previously had four navigation services for the Grid, HierarchicalGridTreeGrid, and MRL functionality. Now we have only three. With the old implementation, on scrolling with virtualized content, we were changing the cell context (the actual shell remained the same) and had problem with the browser not allowing us to focus on an already focused element - we have had to blur the cell focus, change the cell context and focus it again. Now that is no longer an issue. 
  • Touch device enhancements - now if we have a focused cell on scrolling, we blur the cell before detaching the wheel handler. 
  • Application level performance boost with `events stacking`. Use `ngZoneEventColescing: true` 

Const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule, { ngZoneEnetCoalescing: true }); 

Keyboard Navigation Features Integration 

Now let's focus on the keyboard navigation features integration. Our grid has plenty of features and we've considered all of them carefully to ensure that they work properly with the new changes.  

  • Header navigation - we now have a smooth column header and column group navigation. Check out this header interactions list, which explains how to activate a certain feature with a key combination. Live demo.
  • Excel-style filter and default filtering row 
    • Ctrl + Shift + L will open the Excel-style filter/default (row) filter  
  • Advanced filtering 
    • Alt + L opens the advanced filter dialog 
  • Sorting 
    • Ctrl + Arrow up sorts the active column header in ASC order. If the column is already sorted in ASC, it will remove the sorting (tri state none) 
    • Ctrl + Arrow down sorts the active column header in DSC order. If the column is already sorted in DSC, it will remove the sorting (tri state none) 
  • Group by 
    • Shift + Alt + Arrow right to group by the active column. 
    • Shift + Alt + Arrow left ungroup the active column (remove it from the group by criteria) 
  • Multi-column headers 
    • Alt + left/up arrow key – collapse 
    • Alt + right/down arrow key – expand 
  • Column Selection - Space key press - select a column 

Different key combinations

Note: If you are using a screen-reader, keep in mind that on initial header click, we are focusing the whole header container and the screen reader will read all header captions. Following click on the header, the header caption + selection state will be read. Example - Company name, column header selected. 

  • Cell editing - now the tab navigation works only for editable cells (In edit mode). On cell editing with Tab navigation, if we reach the end of the grid, the last cell will be submitted, and the navigation will continue to the next available tab stop element. 
  • Filtering (filtering chips) - Tab navigation for chips is removed, navigation is possible only by using arrow keys. Also: 
    • Chips are part of the column header now 
    • Chips are not focusable elements anymore 
  • Paging - richer accessibility. Added tooltips, aria-labels, and roles. 
  • Default Key combination updates: 
    • Ctrl + any other key works only on real cells, not on a grouped row area. This is a difference compared with the old behavior. GroupBy and Master-Detail don’t work with Ctrl+ arrow keys. 
    • Ctrl + Right/Left Arrow works only on the common cells, summary row, and headers 
    • Home and End (and Ctrl Home/End) works as expected, there are no changes here. 
    • We now provide richer visual styling for the tab stops/header element/body cells/summaries/paging/group by/master-detail/MRL/cell editing 

...

Thanks to the combined efforts of our developers we’ve managed to significantly reduce keyboard navigation complexity. The overall keyboard interaction is now improved, intuitive to use, offering better usability, while ensuring accessibility. We understand the need for continuous innovation and that great features are a result of true collaboration  

Don’t forget to check out the rest of the new features and enhancements that were released as part of our Ignite for Angular 9.1.0 release. Please share any comments or questions in the Comments section below.