Skip to content

fix(a11y): unique names for repeated nav landmarks - #4692

Open
AKnassa wants to merge 1 commit into
facebook:mainfrom
AKnassa:rocky/issue-4681-landmark-unique
Open

fix(a11y): unique names for repeated nav landmarks#4692
AKnassa wants to merge 1 commit into
facebook:mainfrom
AKnassa:rocky/issue-4681-landmark-unique

Conversation

@AKnassa

@AKnassa AKnassa commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #4681 (weekly a11y scan). Clears all 8 landmark-unique baseline entries (Layout, Pagination, TabList x2, TablePagination x2, Toolbar, ToolbarEdgeCompensation).

What this does

Same-type landmarks need distinguishable accessible names. The flagged stories render several <nav> landmarks with identical default labels; one case is a real component gap. Both get fixed at the level they belong to.

What changed

  • Story-level (6 files, existing props only): the Layout, Pagination, TabList, Toolbar, ToolbarEdgeCompensation and TablePagination matrix stories now pass distinct labels to each instance (for example aria-label={'Tabs (' + size + ')'}). No component behavior changes.
  • Component-level (useTablePagination, packages/core): with position='both', one hook call rendered two navs sharing one name, which a story cannot fix. The two navs now get distinct names by interpolating the label into two new i18n keys: "{label} (top)" and "{label} (bottom)". Single-position accessible names stay byte-identical. New keys live in en.json only (fr-FR stays a sparse demo catalog); the base key's translator note now points at the suffix templates.
  • The previously undocumented label config is now in the doc.mjs (EN and dense variants), including the position='both' naming contract.
  • Baseline: 8 entries removed, deletions only. Changeset (patch): the position='both' nav names change for assistive technology; the old duplicate-name behavior was itself the violation.

Judgment call, stated plainly

The "(top)" / "(bottom)" suffix wording is a choice. Alternatives considered: standalone non-interpolated keys (loses the consumer-supplied label), or suffixing only one nav (asymmetric announcements). Interpolated templates keep consumer labels differentiated and translatable as a unit. Happy to reword if you prefer different suffixes.

Verification

43/43 pagination plugin tests (the old test asserting two same-named navs is rewritten, plus a consumer-label interpolation test), 147/147 across the wider pagination/Pagination/i18n slice, core typecheck, eslint clean, and the repo's axe audit with --fail-on-new across all six components: exit 0, "0 new, 13 resolved".

axe landmark-unique (moderate): same-type landmarks need
distinguishable names. Story matrices rendered several navs with
identical default labels — fixed by passing distinct labels through
existing props (Layout, Pagination, TabList, Toolbar,
ToolbarEdgeCompensation, TablePagination stories). Component fix:
useTablePagination position=both emitted two navs with one name from
a single hook call — they now interpolate the label into distinct
top/bottom names via new en.json keys; single-position names stay
byte-identical. label config documented in doc.mjs.
Baseline: -8 entries.

Verified: 43/43 pagination + 147/147 wider slice tests, core
typecheck, eslint clean, axe audit exit 0 (0 new, 13 resolved)
across all six components.

Part of facebook#4681.
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
astryx Ready Ready Preview Aug 3, 2026 9:43pm

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Aug 3, 2026
@AKnassa
AKnassa marked this pull request as ready for review August 4, 2026 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant