Skip to content

fix(lab): add tab stops to scrollable regions - #4691

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

fix(lab): add tab stops to scrollable regions#4691
AKnassa wants to merge 1 commit into
facebook:mainfrom
AKnassa:rocky/issue-4681-scrollable-focus

Conversation

@AKnassa

@AKnassa AKnassa commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Part of #4681 (weekly a11y scan). Clears all 6 scrollable-region-focusable baseline entries (CodeEditor, CodeEditorPerf x2, Outline, Schedule, Stack).

What this does

Scrollable containers with no focusable content are unreachable for keyboard users. Two component fixes in lab and two story-level fixes make each flagged scroll region keyboard-reachable.

What changed

  • CodeEditor (packages/lab): explicit tabIndex={0} on the contenteditable code element. Editable editors already had an effective tab stop (this just materializes the attribute axe inspects); read-only editors genuinely gain one, matching native readonly <textarea> behavior, so keyboard users can reach and scroll them. That read-only change is intentional and pinned by a test. Covers all three CodeEditor/CodeEditorPerf entries.
  • Schedule monthly view (packages/lab): tabIndex={0} on the month grid, which already carries role="grid", aria-readonly and a label. The grid has no interactive descendants today; if day cells or event pills ever become interactive, this should convert to a roving-tabindex pattern (recorded here so the constraint is known).
  • Outline "Scroll Spy" and Stack "Scrollable" stories: the scrollable panes are story-made demo divs, so they get tabIndex, role="region" and an aria-label at the story level. Stack itself is untouched on purpose: a generic layout primitive should not grow a tab stop by default, and that API call belongs to maintainers if ever wanted.
  • Baseline: 6 entries removed, deletions only. No changeset: lab is unpublished-stable (canary) and the rest is stories.

Note on Schedule::Monthly

The violation does not reproduce at the local audit viewport (it fires on CI's). The unit test pins the attribute mechanism either way; the weekly scan will confirm on CI.

Verification

Full lab suite 388/388 and full core suite 5786/5786, storybook typecheck, eslint clean, and the repo's axe audit with --fail-on-new: zero scrollable-region-focusable occurrences across all five components' stories.

axe scrollable-region-focusable (serious): overflow containers with
no focusable content are unreachable by keyboard. Component fixes:
CodeEditor's contenteditable code element gets an explicit
tabIndex=0 (read-only editors gain a tab stop, matching native
readonly textarea); Schedule's monthly grid gets tabIndex=0 (it
already carries role and label). Story fixes: Outline Scroll Spy and
Stack Scrollable panes get tabIndex + role=region + aria-label —
Stack itself is untouched, a layout primitive should not grow a tab
stop by default. Baseline: -6 entries. No changeset (lab + stories).

Verified: lab 388/388 and core 5786/5786 suites, storybook
typecheck, eslint clean, axe audit zero scrollable violations.

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:48
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