Skip to content

Fix ARIA grid structure violations for WCAG 1.3.1 compliance#16823

Merged
ChronosSF merged 18 commits into
masterfrom
copilot/fix-accessibility-issues
May 7, 2026
Merged

Fix ARIA grid structure violations for WCAG 1.3.1 compliance#16823
ChronosSF merged 18 commits into
masterfrom
copilot/fix-accessibility-issues

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 29, 2026

Fix ARIA accessibility issues in igx-grid component

  • Explore repository structure and locate grid component files
  • Understand current ARIA role structure
  • Analyze the specific accessibility violations
  • Add proper ARIA role="rowgroup" to grid header row component
  • Add role="presentation" to toolbar and group-by area components
  • Add role="presentation" to scroll and footer containers
  • Apply fixes to all grid types (grid, tree-grid, hierarchical-grid, pivot-grid)
  • Build project successfully
  • Run code review - no issues found
  • Run security checks - passed
  • Refactor: Move role="presentation" to base directive
  • Document changes

Summary

This PR fixes WCAG 1.3.1 accessibility violations (aria-required-children) in all grid components. The changes ensure that elements with role="grid" only have direct children with allowed ARIA roles (row or rowgroup) per the ARIA specification.

Changes:

  1. Added role="rowgroup" to header row components
  2. Added role="presentation" to base IgxGroupByAreaDirective (inherited by grid and tree-grid variants)
  3. Added role="presentation" to toolbar component
  4. Added role="presentation" to scroll and footer containers
  5. Applied fixes consistently across all grid variants (grid, tree-grid, hierarchical-grid, pivot-grid)
Original prompt

This section details on the original issue you should resolve

<issue_title>Accessibility Insights: Element has children which are not allowed: igx-grid-header-row[tabindex], div[tabindex], button[aria-haspopup], button[tabindex], [role=navigation], [role=button], [role=switch], [role=combobox]</issue_title>
<issue_description>## Description
Based on Accessibility Insights for Web, the following elements are not compliant: igxGrid

  • igniteui-angular version: 19.2.24
  • browser: Edge

Steps to reproduce

  1. Install the Accessibility Insights extension for Edge
  2. Create an example igx-grid table with columns, paginator and toolbar
  3. Run the FastPass check from the notification Launch Pad

Result

What is the actual result after following the steps to reproduce?

We are seeing the following result:

Image

Title: WCAG 1.3.1: Ensure elements with an ARIA role that require child roles contain them (#igxGrid)
Tags: Accessibility, WCAG 1.3.1, aria-required-children

Issue: Ensure elements with an ARIA role that require child roles contain them (aria-required-children - https://accessibilityinsights.io/info-examples/web/aria-required-children)

Target application: CO+I CSP - https://coi-cspw.azurefd.net/supplystore

Element path: #igxGrid

Snippet:

Related paths:
igx-grid-header-row
.igx-grid__tbody-content
.igx-grid__tfoot > div
.me-3
#clearFilters-btn
igx-page-nav
.date-picker-wrapper
button[name="btnColumnHiding"]
button[title="Open exporter dropdown"]
.h-100 > .menu-button.mdc-button--raised.mat-mdc-raised-button
#mat-mdc-slide-toggle-2-button
.input

How to fix:
Fix any of the following:
Element has children which are not allowed: igx-grid-header-row[tabindex], div[tabindex], button[aria-haspopup], button[tabindex], [role=navigation], [role=button], [role=switch], [role=combobox]

Environment: Microsoft Edge version 143.0.0.0

====

This accessibility issue was found using Accessibility Insights for Web 2.46.0 (axe-core 4.10.2), a tool that helps find and fix accessibility issues. Get more information & download this tool at http://aka.ms/AccessibilityInsights.

Expected result

What is the expected result after following the steps to reproduce?
There should not be failed instances

Attachments

Attach a sample if available, and screenshots, if applicable.

Image

</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits January 29, 2026 11:14
Co-authored-by: ChronosSF <2188411+ChronosSF@users.noreply.github.com>
Co-authored-by: ChronosSF <2188411+ChronosSF@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix accessibility compliance for igx-grid components Fix ARIA grid structure violations for WCAG 1.3.1 compliance Jan 29, 2026
Copilot AI requested a review from ChronosSF January 29, 2026 11:23
@viktorkombov viktorkombov self-requested a review March 11, 2026 13:46
@viktorkombov viktorkombov self-assigned this Mar 11, 2026
The ARIA spec for grid/treegrid composites defines a strict role
hierarchy: grid -> rowgroup -> row -> gridcell/columnheader. This commit
aligns the grid templates and components with that structure while
preserving the existing keyboard navigation model.

- Move role="rowgroup" from outer tbody/tfoot layout divs to the inner
  focus-host divs; outer wrappers receive role="presentation" — applies
  to grid, tree-grid, hierarchical-grid and pivot-grid
- Add role="gridcell" to row-selector and drag-indicator wrappers in
  data rows (grid-row, tree-grid-row, hierarchical-row, groupby-row)
- Add role="columnheader" to the equivalent wrappers in grid-header-row
- Add role="row" to IgxGridGroupByRowComponent host (previously absent)
  and role="gridcell" to its toggle, content and selector children
- Add role="row" to igx-grid-filtering-row host; wrap its children
  (input template, scroll arrows, chips area, action buttons) in
  role="gridcell" — scroll-arrow wrappers use display:contents to
  remain layout-transparent

Known limitations (deferred — require structural refactoring):
igx-grid-toolbar, igx-group-by-area and igx-paginator are projected via
ng-content inside the grid host (role="grid"), making them owned
children of the grid in the accessibility tree. Full compliance would
require them to be siblings of role="grid".
@viktorkombov
Copy link
Copy Markdown
Contributor

The ARIA spec for grid/treegrid composites defines a strict role
hierarchy: grid -> rowgroup -> row -> gridcell/columnheader. The above commit
aligns the grid templates and components with that structure while
preserving the existing keyboard navigation model.

  • Move role="rowgroup" from outer tbody/tfoot layout divs to the inner
    focus-host divs; outer wrappers receive role="presentation" — applies
    to grid, tree-grid, hierarchical-grid and pivot-grid
  • Add role="gridcell" to row-selector and drag-indicator wrappers in
    data rows (grid-row, tree-grid-row, hierarchical-row, groupby-row)
  • Add role="columnheader" to the equivalent wrappers in grid-header-row
  • Add role="row" to IgxGridGroupByRowComponent host (previously absent)
    and role="gridcell" to its toggle, content and selector children
  • Add role="row" to igx-grid-filtering-row host; wrap its children
    (input template, scroll arrows, chips area, action buttons) in
    role="gridcell" — scroll-arrow wrappers use display:contents to
    remain layout-transparent

Known limitations (deferred — require structural refactoring):
igx-grid-toolbar, igx-group-by-area and igx-paginator are projected via
ng-content inside the grid host (role="grid"), making them owned
children of the grid in the accessibility tree. Full compliance would
require them to be siblings of role="grid".

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses WCAG 1.3.1 / aria-required-children violations by reshaping the ARIA grid ownership tree so that role="grid" elements own only row/rowgroup descendants, and non-grid UI is marked presentational.

Changes:

  • Move grid header row semantics to the header-row component host (role="rowgroup") and adjust header “action” cell roles.
  • Mark non-grid UI areas (toolbar, group-by area, scroll containers, footer) as role="presentation" across grid variants.
  • Ensure various row “action” UI wrappers participate as proper grid cells (role="gridcell"), and adjust body/footer rowgroup placement.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
projects/igniteui-angular/grids/tree-grid/src/tree-grid.component.html Adjusts body/tfoot/scroll/footer roles to avoid invalid grid-owned roles.
projects/igniteui-angular/grids/tree-grid/src/tree-grid-row.component.html Adds role="gridcell" to row action wrappers (drag/selector).
projects/igniteui-angular/grids/tree-grid/src/tree-grid-group-by-area.component.ts Sets group-by area host role="presentation".
projects/igniteui-angular/grids/pivot-grid/src/pivot-grid.component.html Adjusts body/scroll/tfoot/footer roles for pivot grid.
projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-row.component.html Adds role="gridcell" to row action wrappers (drag/selector).
projects/igniteui-angular/grids/hierarchical-grid/src/hierarchical-grid.component.html Adjusts body/tfoot/scroll/footer roles to avoid invalid grid-owned roles.
projects/igniteui-angular/grids/grid/src/groupby-row.component.ts Adds host role="row" and changes where expanded state is exposed.
projects/igniteui-angular/grids/grid/src/groupby-row.component.html Adds role="gridcell" wrappers and relocates aria-expanded.
projects/igniteui-angular/grids/grid/src/grid.component.html Adjusts body/tfoot/scroll/footer roles and moves rowgroup responsibility to tbody-content.
projects/igniteui-angular/grids/grid/src/grid-row.component.html Adds role="gridcell" to row action wrappers (drag/selector).
projects/igniteui-angular/grids/core/src/toolbar/grid-toolbar.component.ts Sets toolbar host role="presentation".
projects/igniteui-angular/grids/core/src/headers/grid-header-row.component.ts Sets header-row host role="rowgroup".
projects/igniteui-angular/grids/core/src/headers/grid-header-row.component.html Removes inner rowgroup role and adds header action cell roles.
projects/igniteui-angular/grids/core/src/grouping/grid-group-by-area.component.ts Sets group-by area host role="presentation".
projects/igniteui-angular/grids/core/src/filtering/base/grid-filtering-cell.component.ts Sets filtering cell host role="gridcell".
package-lock.json Lockfile metadata changes (appears unrelated to ARIA work).

You can also share your feedback on Copilot code review. Take the survey.

Comment thread projects/igniteui-angular/grids/grid/src/groupby-row.component.html
Comment thread projects/igniteui-angular/grids/grid/src/groupby-row.component.ts
@ChronosSF
Copy link
Copy Markdown
Member

@viktorkombov , thank you! Please clean up the PR (resolve conflicts) and address or dismiss Copilot comments then I can verify it and communicate with the user who reported it.

@viktorkombov viktorkombov marked this pull request as ready for review March 13, 2026 10:16
Comment thread projects/igniteui-angular/grids/grid/src/grid.component.spec.ts Fixed
viktorkombov and others added 2 commits March 13, 2026 12:20
…tion or class'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
* @internal
*/
@HostBinding('attr.role')
public role = 'presentation';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be added to IgxGroupByAreaDirective instead

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Moved role="presentation" binding to IgxGroupByAreaDirective base class in commit 6d571a0.

* @internal
*/
@HostBinding('attr.role')
public role = 'presentation';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be added to IgxGroupByAreaDirective instead

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Moved role="presentation" binding to IgxGroupByAreaDirective base class in commit 6d571a0.

@ChronosSF ChronosSF added ✅ status: verified Applies to PRs that have passed manual verification and removed ❌ status: awaiting-test PRs awaiting manual verification labels Mar 18, 2026
Co-authored-by: ChronosSF <2188411+ChronosSF@users.noreply.github.com>
Copilot AI requested a review from ChronosSF March 18, 2026 16:03
@ChronosSF ChronosSF merged commit 4f4f549 into master May 7, 2026
6 checks passed
@ChronosSF ChronosSF deleted the copilot/fix-accessibility-issues branch May 7, 2026 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

5 participants