Skip to content

add sectionheader and sectionfooter roles - #1931

Merged
jnurthen merged 13 commits into
mainfrom
header-footer-roles
Dec 11, 2024
Merged

jnurthen merged 13 commits into
mainfrom
header-footer-roles

Conversation

@scottaohara

@scottaohara scottaohara commented May 9, 2023 •

Copy link
Copy Markdown
Member

adds proposed header and footer roles to allow authors to identify areas of the page that would fit the more general HTML definition for the elements of the same name (and would not be considered landmark elements).

These would also allow for the respective HTML elements to expose these new roles - essentially 'renamed' group roles - if they are given properties important to accessibility (focusable, named) but are not meeting the conditions to be exposed as banner / contentinfo landmarks. The alternative is to just expose the elements as groups, which is doable, but arguably also overloads the use of the group role.

Closes #1915

Implementation tracking


Preview | Diff

@scottaohara scottaohara left a comment •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

need to remove instances of referring to fieldset that got copied over accidentally.

Comment thread index.html Outdated
Comment thread index.html Outdated
@jnurthen
jnurthen self-requested a review May 11, 2023 17:11
@jnurthen
jnurthen requested a review from cookiecrook May 11, 2023 17:12
@spectranaut
spectranaut self-requested a review May 11, 2023 19:40
@cookiecrook

cookiecrook commented May 15, 2023 •

Copy link
Copy Markdown
Contributor

@scottaohara wrote:

AX API
    AXRole: AXGroup
    AXSubrole: <nil>
    AXRoleDescription: header/footer

Seems reasonable. Checking with others before confirming.

@cookiecrook

cookiecrook commented May 16, 2023 •

Copy link
Copy Markdown
Contributor

@cookiecrook wrote:

[AX API proposals seem] reasonable. Checking with others before confirming.

No comments in 24h. AX API proposals okay as is. Thanks.

Comment thread index.html Outdated

@spectranaut spectranaut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bear with me as I work out my thoughts on this one because I'm not sure where I land -- whether to introduce these new roles or to leave the distinction between landmark header/footer and not-landmark header/footers in html-aam entirely.

Just to be clear, if this PR lands, the corresponding change in core-aam would be that https://w3c.github.io/html-aam/#el-header and https://w3c.github.io/html-aam/#el-footer point to these new roles and say use these mappings?

I guess one reason why we should introduce these roles is because it is a place to document the concept of a "section header" and "section footer" as apposed to the landmark header/banner and landmaker footer/contentinfo. This makes me feel like there should be some very author-specific guidance about this, and makes me realize we aren't tracking changes to MDN with changes in the spec. Should we be tracking MDN changes? Alternatively, it seems almost too basic, but should there be an APG example for this?

Also, where is the current author facing documentation that says a html header and footer are considered landmarks in these cases and not in these other cases? I just check mdn and it is not there.

Also, would we want a "screen reader guidance" section as well? Essentially explaining you can expose this information when you feel like it's necessary, as @cookiecrook mentioned in the VoiceOver case?

@cookiecrook

cookiecrook commented May 18, 2023 •

Copy link
Copy Markdown
Contributor

Also, would we want a "screen reader guidance" section as well? Essentially explaining you can expose this information when you feel like it's necessary, as @cookiecrook mentioned in the VoiceOver case?

No AT changes are needed on Mac. This is only an engine change that results in a different role description. Nothing more.

On the call today, @scottaohara mentioned the same was true on Windows.

@scottaohara

Copy link
Copy Markdown
Member Author

@spectranaut probably not a bad idea to add a check for has MDN documentation been updated - these docs are often behind the curve with a11y info/updates. header mentions the 'scoped' nature of the header element - lightly, now. footer calls out an old webkit bug in its accessibility section.

@scottaohara

scottaohara commented Aug 16, 2023 •

Copy link
Copy Markdown
Member Author

@jnurthen @cookiecrook @spectranaut any other thoughts on this preventing it from merging? got reminded of it when reviewing the (now linked) WPT.

re: author guidance on when a header/footer is a section header/footer vs the landmarks. that can be added to MDN, but that's blocked on this change being made. One could argue the info could be more overtly stated with the current reality of how these elements work. But I would rather make one change than two.

@cookiecrook

cookiecrook commented Aug 16, 2023 •

Copy link
Copy Markdown
Contributor

@jnurthen @cookiecrook @spectranaut any other thoughts on this preventing it from merging? got reminded of it when reviewing the (now linked) WPT.

re: author guidance on when a header/footer is a section header/footer vs the landmarks. that can be added to MDN, but that's blocked on this change being made. One could argue the info could be more overtly stated with the current reality of how these elements work. But I would rather make one change than two.

I was suggesting the role name be changed from header/footer to sectionheader/sectionfooter to prevent author confusion with the existing role banner…

Comment thread index.html Outdated
@scottaohara

Copy link
Copy Markdown
Member Author

thanks @cookiecrook. for some reason i had a memory of already doing this, but clearly my memory was faulty. i've actually done it now.

@spectranaut

spectranaut commented Aug 17, 2023 •

Copy link
Copy Markdown
Contributor

Per our new process, changes to the ARIA spec can't land until there are implementations or implementation commitments, and related changes to the AAMs/Accname, so I think you need to open all those PRs and bugs on browsers.

But I just realized we sort of need an intermediary, because we shouldn't open bugs on browsers until we have "consensus" from the working group... we we need a way of keeping track of that some how. I think it used to be that once we had consensus we merged, and that is how we "kept track" of what had consensus.

@scottaohara

scottaohara commented Aug 17, 2023 •

Copy link
Copy Markdown
Member Author

yes, there does seem to be something with this revised process that needs working out, as I didn't think it would make sense to file bugs until reviews were completed (and i did the work james requested and i flubbed on actually doing, until yesterday).

also, as we've already had a few meetings (triage, then the meeting where i actually babbled on about the proposal - resulting in me doing the work, and THEN we did initial triage of the PR) isn't the fact there were reviewers assigned (and anyone else can also review now) the end point of the consensus process? E.g., once we have approving reviews, then that means there is consensus. If more consensus is needed after that, it seems like the process is overcomplicated, or we aren't doing consensus right.

@spectranaut

Copy link
Copy Markdown
Contributor

Ah good point, @scottaohara -- three reviews = consensus. So, we can open issues on implementations after there are three reviews, and we can merge after there is at least one implementation and implementation commitment

@scottaohara scottaohara changed the title add proposed header and footer roles add proposed sectionheader and sectionfooter roles Oct 24, 2023

@spectranaut spectranaut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think these sections look good! Very clear description.

scottaohara added a commit to w3c/core-aam that referenced this pull request Oct 26, 2023
@spectranaut

Copy link
Copy Markdown
Contributor

Assigning to myself to make tests and issues on browsers.

cdesouza-chromium added a commit to brave/brave-core that referenced this pull request Sep 3, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
mkarolin pushed a commit to brave/brave-core that referenced this pull request Sep 3, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
cdesouza-chromium added a commit to brave/brave-core that referenced this pull request Sep 5, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
cdesouza-chromium added a commit to brave/brave-core that referenced this pull request Sep 5, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
mkarolin pushed a commit to brave/brave-core that referenced this pull request Sep 5, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
cdesouza-chromium added a commit to brave/brave-core that referenced this pull request Sep 6, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
cdesouza-chromium added a commit to brave/brave-core that referenced this pull request Sep 9, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
mkarolin pushed a commit to brave/brave-core that referenced this pull request Sep 9, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
cdesouza-chromium added a commit to brave/brave-core that referenced this pull request Sep 10, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
mkarolin pushed a commit to brave/brave-core that referenced this pull request Sep 10, 2024
This constant has been renamed to `ax::mojom::Role::kSectionFooter`.

Chromium change:
https://chromium.googlesource.com/chromium/src/+/03a093c456608e8deb9e0c7ce2077f09022ac3f3

commit 03a093c456608e8deb9e0c7ce2077f09022ac3f3
Author: Jocelyn Tran <jocelyntran@google.com>
Date:   Fri Aug 16 15:53:13 2024 +0000

    [A11y] Rename kHeaderAsNonLandmark and kFooterAsNonLandmark

    Two new roles are being added to aria: sectionheader and sectionfooter
    [1]. header scoped to the main element or a sectioning content element
    will map to sectionheader and footer scoped to the main element or a
    sectioning content element will map to sectionfooter.

    There are two existing internal roles, kHeaderAsNonLandmark and
    kFooterAsNonLandmark, that represent these concepts so only the role
    name and output strings for the platform APIs have to be updated.

    [1] w3c/aria#1931

    Fixed: 337094897, 358159988, 358192585
@scottaohara

Copy link
Copy Markdown
Member Author

confirming that Edge/Chrome (both msaa/ia2 and uia trees) expose the sectionheader and sectionfooter roles.

@scottaohara

Copy link
Copy Markdown
Member Author

Ah good point, @scottaohara -- three reviews = consensus. So, we can open issues on implementations after there are three reviews, and we can merge after there is at least one implementation and implementation commitment

@spectranaut since this has been implemented in chromium, and the other browsers have their accepted bugs on them, seems we're good to merge per your last comment?

@jnurthen
jnurthen merged commit 80753f9 into main Dec 11, 2024
@jnurthen jnurthen removed the waiting for implementations Cannot be merged until there are two browser impls or one impl + impl commit label Dec 11, 2024
github-actions Bot added a commit that referenced this pull request Dec 11, 2024
SHA: 80753f9
Reason: push, by jnurthen

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@scottaohara
scottaohara deleted the header-footer-roles branch May 29, 2025 14:53
jwidar pushed a commit to jwidar/LatencyZeroGithub that referenced this pull request Sep 16, 2025
…r role tests, a=testonly

Automatic update from web-platform-tests
ARIA: Add sectionheader and sectionfooter role tests (#46142)

Adding new roles to .tenative file until implementation is complete

See w3c/aria#1931
--

wpt-commits: 6618b73099d0aa8c9feed33a62f79d706dbb75f0
wpt-pr: 46142
pkra added a commit that referenced this pull request Sep 25, 2025
Updates roleInfo using the current manual process. Changes are due to #2076, #1662, #1945, #2581, #1931, #1991, #1862

Part of #2501

Also resolves #2234
chutchins25 added a commit to dequelabs/axe-core that referenced this pull request Jul 29, 2026
Adds the ARIA 1.3 sectionheader and sectionfooter roles (w3c/aria#1931)
as concrete structural roles with superclass section.

Closes #4734
straker pushed a commit to dequelabs/axe-core that referenced this pull request Jul 29, 2026
Adds the new ARIA 1.3 `sectionheader` and `sectionfooter` roles to
axe-core's standards data.

## What & why

Per [w3c/aria#1931](w3c/aria#1931) (merged into
the ARIA spec `main`), `sectionheader` and `sectionfooter` are new
**concrete structural roles** with superclass `section`. axe-core did
not recognize them, so `role="sectionheader"` / `role="sectionfooter"`
were flagged as invalid roles.

Definitions were grounded directly against the spec source (`w3c/aria`
`main`):
- `roleInfo.js` — `parentRoles: ["section"]`, no required / prohibited /
local (non-global) properties.
- `index.html` characteristics table — **Is Abstract:** no (concrete),
**Name From:** author (so no `nameFromContent`), **Accessible Name
Required:** no.

They are modeled on the existing `blockquote` precedent (`type:
'structure', superclassRole: ['section']`).

## Note on scope — bundling `sectionfooter`

The issue (#4734) names only `sectionheader`, but the spec introduced
`sectionheader` and `sectionfooter` together and there is no separate
`sectionfooter` issue. They are bundled here as one cohesive "ARIA 1.3
section header/footer roles" change.

## Out of scope / follow-up

The updated HTML-AAM implicit-role mapping (`<header>` / `<footer>`
scoped inside sectioning content → implicit `sectionheader` /
`sectionfooter`) is **not** included here — it has a much larger blast
radius (landmark/region computations, `aria-allowed-role`) and will be
tracked as a separate issue.

## Tests
- `aria-roles` integration HTML/JSON — pass cases for both roles.
- `aria-roles` virtual-rule — pass cases for both roles.
- Verified `abstractrole` / `fallbackrole` / `unsupportedrole` /
`aria-allowed-role` check suites still pass.

Closes #4734
patrickbdevaney added a commit to patrickbdevaney/manuk that referenced this pull request Aug 29, 2026
…d existed in the entrance the web does not use

TRACK B, second consecutive. Target chosen by SURVEY, not by count.

THE SURVEY SAID SOMETHING THE COUNT COULD NOT. `wai-aria` was 238/434 = 54.8%, the lowest a11y row.
Classifying all 172 failing subtests by the SUBJECT element's `role` attribute rather than by file:

  114  (66.3%)  role token CASE                    role="foo Link", role=" buTtOn"
   33  (19.2%)  token ABSENT from the vocabulary   sectionfooter, grid, rowgroup, code, time…
   16  ( 9.3%)  token COLLAPSED onto a near role   gridcell -> cell, menuitemcheckbox -> menuitem
    5  ( 2.9%)  no role attr (implicit mapping)
    4  ( 2.3%)  role=none/presentation conflict resolution

⭐ Two-thirds of the lowest row on the a11y board was ONE LINE. A count says "171 role failures, a
long grind"; the survey says "one expression, then a vocabulary".

⭐⭐⭐ THE CASE FOLD ALREADY EXISTED — IN THE ENTRANCE THE WEB DOES NOT USE. `Role::parse` is
`from_aria_token(&tok.trim().to_ascii_lowercase())` and is what manuk-agent calls. `role_of` — the
path a real `role="…"` ATTRIBUTE takes — called the raw matcher, so `role="BUTTON"` matched nothing
and the element fell through to its implicit role. This is t1353's "two entrances, one unguarded"
with the sides swapped: the GUARDED entrance was the one we built for ourselves and the unguarded one
was the web's — the worse way round, because our own tests all come in through our own door. It
matters past conformance because of the FALLBACK-TOKEN form, `role="foo Link"` — an unknown token
then a real one — which is how authors ship forward-compatible roles.

~30 ABSENT TOKENS, AND ABSENT MEANS `generic`: code, time, term, definition, deletion, insertion,
emphasis, strong, subscript, superscript, mark, blockquote, caption, figure, meter, grid, rowgroup,
searchbox, scrollbar, log, timer, marquee, math, note, application, suggestion, sectionheader,
sectionfooter — plus their HTML spellings (<em>, <strong>, <code>, <sub>, <sup>, <mark>, <time>,
<del>, <s>, <ins>, <dfn>, <dd>, <blockquote>, <figure>, <meter>, <output>, <optgroup>, <dir>,
thead/tbody/tfoot, input[type=search]). A tree that answers "a box" about a word the author marked up
on purpose cannot be the agent's perception layer — that is I3's own claim, not a conformance point.

A COLLAPSE READS AS A PLAUSIBLE NEIGHBOUR, WHICH IS WHY IT SURVIVES REVIEW. `gridcell` was grounded
on `cell` and `menuitemcheckbox`/`menuitemradio` on `menuitem`, WITH A COMMENT SAYING SO — the t1303
shape, a workaround's comment as a claim that dies silently. But `menuitemcheckbox` IS the
announcement that the item carries a state. ⚠ Un-collapsing would have silently broken manuk-agent,
which targets by role NAME, so `Role::matches` now lets the coarse token match the specific role: A
PRECISION GAIN THAT DROPS A MATCH IS A REGRESSION, and that is a ratchet requirement, not politeness.
The same reasoning threads GridCell into `name_from_content` and the two menu-item roles into
`is_interactive` — they had those properties as Cell/MenuItem.

⭐ AND ONE OF THEM IS A REAL-PAGE BUG. A `<footer>` inside an `<article>` is NOT the page's footer.
banner/contentinfo are LANDMARKS — a screen reader offers a jump list of them and an agent reads them
as the page's chrome — so a blog index with thirty articles was publishing THIRTY `contentinfo`
landmarks, which is worse than none: the one real page footer stops being findable. ARIA 1.3
(w3c/aria#1931) scopes them to sectionheader/sectionfooter when an article/aside/main/nav/section
ancestor exists.

THE RECEIPT:

  suite       BEFORE            AFTER             delta
  wai-aria    238/434  54.8%    387/434  89.2%    +149
  html-aam    253/335  75.5%    281/335  83.9%     +28
  accname     380/484  78.5%    380/484  78.5%       0   CONTROL
  a11y TOTAL  871/1253 69.5%   1048/1253 83.6%    +177   HANG/CRASH 0

AND THE SESSION'S TWO TRACK-B TICKS TOGETHER: 819/1253 = 65.4% -> 1048/1253 = 83.6%, +229 subtests,
on a subsystem with no engine tick since t1254 (2026-08-14), frozen at 63.8%. The board's Track-B bar
is ">=90% node match"; wai-aria is now 89.2%.

GATE `an_aria_role_token_is_case_insensitive_and_the_vocabulary_is_complete`
(agent/tests/g_a11y_role_vocabulary.rs) — 8 arms: four case spellings of one token; the
fallback-token form; 28 previously-absent tokens; the two un-collapsed roles; THE `Role::matches`
COMPATIBILITY ARM; 18 HTML implicit mappings; <footer>/<header> landmark scoping with top-level
CONTROLS for both; and controls that an unknown token still falls through and a plain <div> is still
honestly `generic`. RED under THREE mutations: N1 restore `from_aria_token` in `role_of` ->
role="BUTTON" reads "generic"; N2 re-collapse the menu-item roles -> "menuitem"; N3 make
`in_sectioning_content` always false -> a nav's footer reads "contentinfo".

PERF: none — a token match and a short ancestor walk on <header>/<footer> only.

TICK SHAPE: capability — the accessibility tree (Track B), on the board's own nudge.

WIKI: docs/wiki/dom-semantics.md
patrickbdevaney added a commit to patrickbdevaney/manuk that referenced this pull request Aug 29, 2026
…d existed in the entrance the web does not use

TRACK B, second consecutive. Target chosen by SURVEY, not by count.

THE SURVEY SAID SOMETHING THE COUNT COULD NOT. `wai-aria` was 238/434 = 54.8%, the lowest a11y row.
Classifying all 172 failing subtests by the SUBJECT element's `role` attribute rather than by file:

  114  (66.3%)  role token CASE                    role="foo Link", role=" buTtOn"
   33  (19.2%)  token ABSENT from the vocabulary   sectionfooter, grid, rowgroup, code, time…
   16  ( 9.3%)  token COLLAPSED onto a near role   gridcell -> cell, menuitemcheckbox -> menuitem
    5  ( 2.9%)  no role attr (implicit mapping)
    4  ( 2.3%)  role=none/presentation conflict resolution

⭐ Two-thirds of the lowest row on the a11y board was ONE LINE. A count says "171 role failures, a
long grind"; the survey says "one expression, then a vocabulary".

⭐⭐⭐ THE CASE FOLD ALREADY EXISTED — IN THE ENTRANCE THE WEB DOES NOT USE. `Role::parse` is
`from_aria_token(&tok.trim().to_ascii_lowercase())` and is what manuk-agent calls. `role_of` — the
path a real `role="…"` ATTRIBUTE takes — called the raw matcher, so `role="BUTTON"` matched nothing
and the element fell through to its implicit role. This is t1353's "two entrances, one unguarded"
with the sides swapped: the GUARDED entrance was the one we built for ourselves and the unguarded one
was the web's — the worse way round, because our own tests all come in through our own door. It
matters past conformance because of the FALLBACK-TOKEN form, `role="foo Link"` — an unknown token
then a real one — which is how authors ship forward-compatible roles.

~30 ABSENT TOKENS, AND ABSENT MEANS `generic`: code, time, term, definition, deletion, insertion,
emphasis, strong, subscript, superscript, mark, blockquote, caption, figure, meter, grid, rowgroup,
searchbox, scrollbar, log, timer, marquee, math, note, application, suggestion, sectionheader,
sectionfooter — plus their HTML spellings (<em>, <strong>, <code>, <sub>, <sup>, <mark>, <time>,
<del>, <s>, <ins>, <dfn>, <dd>, <blockquote>, <figure>, <meter>, <output>, <optgroup>, <dir>,
thead/tbody/tfoot, input[type=search]). A tree that answers "a box" about a word the author marked up
on purpose cannot be the agent's perception layer — that is I3's own claim, not a conformance point.

A COLLAPSE READS AS A PLAUSIBLE NEIGHBOUR, WHICH IS WHY IT SURVIVES REVIEW. `gridcell` was grounded
on `cell` and `menuitemcheckbox`/`menuitemradio` on `menuitem`, WITH A COMMENT SAYING SO — the t1303
shape, a workaround's comment as a claim that dies silently. But `menuitemcheckbox` IS the
announcement that the item carries a state. ⚠ Un-collapsing would have silently broken manuk-agent,
which targets by role NAME, so `Role::matches` now lets the coarse token match the specific role: A
PRECISION GAIN THAT DROPS A MATCH IS A REGRESSION, and that is a ratchet requirement, not politeness.
The same reasoning threads GridCell into `name_from_content` and the two menu-item roles into
`is_interactive` — they had those properties as Cell/MenuItem.

⭐ AND ONE OF THEM IS A REAL-PAGE BUG. A `<footer>` inside an `<article>` is NOT the page's footer.
banner/contentinfo are LANDMARKS — a screen reader offers a jump list of them and an agent reads them
as the page's chrome — so a blog index with thirty articles was publishing THIRTY `contentinfo`
landmarks, which is worse than none: the one real page footer stops being findable. ARIA 1.3
(w3c/aria#1931) scopes them to sectionheader/sectionfooter when an article/aside/main/nav/section
ancestor exists.

THE RECEIPT:

  suite       BEFORE            AFTER             delta
  wai-aria    238/434  54.8%    387/434  89.2%    +149
  html-aam    253/335  75.5%    281/335  83.9%     +28
  accname     380/484  78.5%    380/484  78.5%       0   CONTROL
  a11y TOTAL  871/1253 69.5%   1048/1253 83.6%    +177   HANG/CRASH 0

AND THE SESSION'S TWO TRACK-B TICKS TOGETHER: 819/1253 = 65.4% -> 1048/1253 = 83.6%, +229 subtests,
on a subsystem with no engine tick since t1254 (2026-08-14), frozen at 63.8%. The board's Track-B bar
is ">=90% node match"; wai-aria is now 89.2%.

GATE `an_aria_role_token_is_case_insensitive_and_the_vocabulary_is_complete`
(agent/tests/g_a11y_role_vocabulary.rs) — 8 arms: four case spellings of one token; the
fallback-token form; 28 previously-absent tokens; the two un-collapsed roles; THE `Role::matches`
COMPATIBILITY ARM; 18 HTML implicit mappings; <footer>/<header> landmark scoping with top-level
CONTROLS for both; and controls that an unknown token still falls through and a plain <div> is still
honestly `generic`. RED under THREE mutations: N1 restore `from_aria_token` in `role_of` ->
role="BUTTON" reads "generic"; N2 re-collapse the menu-item roles -> "menuitem"; N3 make
`in_sectioning_content` always false -> a nav's footer reads "contentinfo".

PERF: none — a token match and a short ancestor walk on <header>/<footer> only.

TICK SHAPE: capability — the accessibility tree (Track B), on the board's own nudge.

WIKI: docs/wiki/dom-semantics.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider adding a 'header' and 'footer' role

6 participants