Skip to content

Defer focusZone initialization to avoid blocking paint#7767

Draft
LisaKr wants to merge 2 commits intomainfrom
defer-focus-zone-init
Draft

Defer focusZone initialization to avoid blocking paint#7767
LisaKr wants to merge 2 commits intomainfrom
defer-focus-zone-init

Conversation

@LisaKr
Copy link
Copy Markdown

@LisaKr LisaKr commented Apr 20, 2026

Closes #

focusZone() synchronously walks the entire container DOM and sets tabindex="-1" on all focusable elements when it initializes. For a list with 25 rows (e.g. GitHub issues list), this takes ~18ms. The tabindex mutations also trigger a React re-render of the entire list (~48ms total blocked before paint).

This PR wraps the beginFocusManagement() call inside useFocusZone in requestAnimationFrame so it runs after the browser paints instead of blocking the initial render.

Why this is safe:

  • Setting tabindex is invisible — it doesn't change anything the user can see
  • Keyboard navigation activating one frame later (~16ms) is imperceptible since users can't press keys before they see the page
  • The AbortController cleanup still works via cancelAnimationFrame + abort()

Changelog

Changed

  • useFocusZone now defers focusZone() initialization to a requestAnimationFrame callback to avoid blocking paint on large lists

New

Removed

Rollout strategy

  • Patch release

Testing & Reviewing

  • TreeView tests updated to flush the deferred RAF via vi.advanceTimersByTime(16) after render (tests already use vi.useFakeTimers)
  • ActionList and ActionBar tests pass without changes
  • All 51 TreeView tests pass, all 15 ActionList tests pass

Merge checklist

  • Added/updated tests
  • Added/updated documentation
  • Added/updated previews (Storybook)
  • Changes are SSR compatible
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge
  • (GitHub staff only) Integration tests pass at github/github-ui

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 20, 2026

⚠️ No Changeset found

Latest commit: 1e85347

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

⚠️ Action required

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Check the integration testing docs for step-by-step instructions. Or, apply the integration-tests: skipped manually label to skip these checks.

To publish a canary release for integration testing, apply the Canary Release label to this PR.

@github-actions github-actions bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant