Skip to content

Checkbox: replace useLayoutEffect with ref callback for indeterminate#7765

Draft
alexus37 wants to merge 3 commits intomainfrom
checkbox-ref-callback-indeterminate
Draft

Checkbox: replace useLayoutEffect with ref callback for indeterminate#7765
alexus37 wants to merge 3 commits intomainfrom
checkbox-ref-callback-indeterminate

Conversation

@alexus37
Copy link
Copy Markdown

Summary

Replaces useLayoutEffect and useEffect in the Checkbox component with a ref callback pattern, eliminating layout effects from every Checkbox render.

Changes

  • useLayoutEffect → ref callback: Uses useCallback + useMergedRefs to set .indeterminate on the DOM node synchronously during commit (same timing guarantees, no registered effect)
  • useEffect → inline JSX: Replaces the imperative aria-checked effect with a declarative aria-checked={indeterminate ? 'mixed' : undefined} attribute. Non-indeterminate checkboxes rely on native checked state for accessibility.
  • Removed unused imports: useEffect, useLayoutEffect, useProvidedRefOrCreate

Motivation

Layout effects run synchronously after DOM mutations and block painting. While individually cheap, they add up in pages rendering many checkboxes (e.g., list views with bulk selection). This change removes one layout effect and one regular effect per Checkbox instance.

Testing

  • All 11 existing Checkbox tests pass
  • Updated aria-checked test to reflect that non-indeterminate checkboxes use native checked state

Closes #7764

Replace useLayoutEffect + useEffect with a ref callback pattern using
useMergedRefs to set the indeterminate DOM property. This eliminates
layout effects from every Checkbox render while maintaining the same
synchronous timing guarantees.

- Use useCallback ref to set .indeterminate on the DOM node
- Merge forwarded ref with indeterminate callback via useMergedRefs
- Replace imperative aria-checked useEffect with inline JSX attribute
- Update tests to reflect that non-indeterminate checkboxes rely on
  native checked state for accessibility

Closes #7764

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 17, 2026

🦋 Changeset detected

Latest commit: b13ac8a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another 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 17, 2026
alexus37 and others added 2 commits April 17, 2026 14:20
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

Checkbox: replace useLayoutEffect with ref callback for indeterminate prop

1 participant