Omit redundant role="heading" when rendering native h1-h6 elements#2845
Omit redundant role="heading" when rendering native h1-h6 elements#2845KAMRONBEK wants to merge 1 commit into
Conversation
When role='heading' (or the deprecated accessibilityRole='header') is used, createElement already maps the element to h1-h6 via propsToAccessibilityComponent, but createDOMProps still emitted role='heading' on the DOM node. <h1 role="heading"> is a redundant role per ARIA in HTML and fails axe audits. Skip the role attribute when the resolved element type is already a native heading element. Non-heading elements with role='heading' are unaffected. Fix necolas#2780
|
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 975af4d:
|
|
@necolas TL;DR: |
Problem
<Text accessibilityRole="header">(orrole="heading") renders<h1 role="heading">. The explicitroleis redundant on a native heading element per the W3C ARIA-in-HTML spec, and it fails axe-core audits ("Page must contain a level-one heading" reportsh1[role="heading"]as insufficient).Root cause
createElementalready maps theheadingrole to a semantich1–h6element viaAccessibilityUtil.propsToAccessibilityComponent(usingaria-level/accessibilityLevel, defaulting toh1), butcreateDOMPropsthen unconditionally emitsdomProps.rolefrompropsToAriaRole, duplicating the semantics on the DOM node.Fix
In
modules/createDOMProps/index.js, skip emitting theroleattribute only when it would be redundant:role === 'heading'and the resolvedelementTypeis alreadyh1–h6. All other roles, androle="heading"on non-heading elements (e.g. a<div role="heading" aria-level="2">), are emitted exactly as before. (Other roles that map to native elements, e.g.button, have the same pattern — this PR is scoped toheading, the case axe flags and #2780 reports; happy to extend if preferred.)Tests
Added cases to
modules/createDOMProps/__tests__/index-test.js:role: 'heading'on each ofh1–h6emits noroleattributeaccessibilityRole: 'header'onh1emits noroleattributerole: 'heading'+aria-levelon adivstill emitsrole="heading"(and keepsaria-level)accessibilityRole: 'header'on adivstill emitsrole="heading"The two heading-element tests fail without the fix. Full jest dom + node suites,
prettier --check,eslint, andflowall pass (no existing snapshots reference the heading role).Fixes #2780