Skip to content

Fix Button loading announcements - #8528

Open
siddharthkp wants to merge 2 commits into
mainfrom
fix/button-loading-announcement
Open

siddharthkp wants to merge 2 commits into
mainfrom
fix/button-loading-announcement

Conversation

@siddharthkp

@siddharthkp siddharthkp commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Fixes github/primer#7110

Ensure Button loading messages reach the live region on the first transition to loading, including when React Strict Mode re-runs effects. Preserve cancellation after a real unmount and add a focused Storybook reproduction.

Changelog

New

  • Added a Button loading-announcement development story.

Changed

  • Button announces its loading message when entering the loading state.
  • Live-region cleanup distinguishes Strict Mode effect cleanup from a real unmount.

Removed

  • None.

Rollout strategy

  • No changes needed in github/github-ui
  • Needs changes in github/github-ui
  • Ships with feature flag(s)
  • Not sure
  • None

Testing & Reviewing

  • Passed: npm test -- --run packages/react/src/live-region/__tests__/Announce.test.tsx packages/react/src/Button/__tests__/Button.test.tsx (67 tests).
  • Passed: npm run type-check --workspace=@primer/react.
  • Passed: DOM verification in Loading Announcement; the first activation writes “Exporting repository” to the polite live region.
  • Blocked: npm run build because the local install is missing the Rolldown native binding (@rolldown/binding-darwin-arm64).

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

changeset-bot Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9642198

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

@siddharthkp
siddharthkp requested a balanced review from Copilot October 12, 2026 20:48
@github-actions github-actions Bot added staff Author is a staff member integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm labels Oct 12, 2026
@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.

Copilot AI 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.

🟢 Approval recommended

The focused implementation is supported by regression coverage for both Strict Mode replay and real unmounting.

0 open findings

What changed in this PR

Fixes Button loading announcements under React Strict Mode while preserving unmount cancellation.

Changes:

  • Defers live-region cleanup to distinguish Strict Mode effect replay from unmounting.
  • Enables loading announcements and adds regression tests.
  • Adds a manual Storybook reproduction and patch changeset.
File Description
packages/​react/​src/​live-region/​Announce.tsx Makes announcement cleanup Strict Mode-safe.
packages/​react/​src/​live-region/​__tests__/​Announce.test.tsx Tests Strict Mode and unmount behavior.
packages/​react/​src/​Button/​ButtonBase.tsx Announces loading messages when shown.
packages/​react/​src/​Button/​Button.dev.stories.tsx Adds an interactive reproduction.
packages/​react/​src/​Button/​__tests__/​Button.test.tsx Verifies the loading live-region message.
.changeset/​bright-buttons-announce.md Documents the patch-level fix.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@github-actions
github-actions Bot temporarily deployed to storybook-preview-8528 October 12, 2026 20:57 Inactive
@siddharthkp siddharthkp changed the title Fix Button loading announcements in Strict Mode Fix Button loading announcements Oct 12, 2026
@primer-integration

primer-integration Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Integration test results from github/github-ui PR:

Waiting  Changes   Waiting
Failed  CI   Failed
Waiting  VRT   Waiting
Running  Projects   Running

CI check runs linting, type checking, and unit tests. Check the workflow logs for specific failures.

Need help? If you believe this failure is unrelated to your changes, please reach out to the Primer team for assistance.

@siddharthkp
siddharthkp requested a review from joshblack October 12, 2026 21:04
@siddharthkp
siddharthkp marked this pull request as ready for review October 12, 2026 21:04
@siddharthkp
siddharthkp requested a review from a team as a code owner October 12, 2026 21:04
@github-actions github-actions Bot added integration-tests: failing Changes in this PR cause breaking changes in gh/gh and removed integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm labels Oct 12, 2026
Comment on lines +135 to +144
const element = ref.current
return () => {
if (savedAnnouncement.current !== null) {
savedAnnouncement.current.cancel()
savedAnnouncement.current = null
}
// StrictMode reconnects the rendered element before the next task.
// eslint-disable-next-line @eslint-react/web-api/no-leaked-timeout -- this task must outlive effect cleanup
cleanupTimeout.current = setTimeout(() => {
if (!element?.isConnected && savedAnnouncement.current !== null) {
savedAnnouncement.current.cancel()
savedAnnouncement.current = null
}
}, 0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think the underlying issue is our useEffectOnce usage since it won't fire twice 😞 If we want to fix this, I think we would remove that hook usage (and maybe lint against it?) and do something like:

useEffect(() => {
  if (announceOnShow) {
    announce()
  }
}, []);

Which would fire twice in StrictMode but would correctly coordinate with the cleanup effect here.

I think this would also need a change in the cleanup effect too for the previousAnnouncementText:

  useEffect(() => {
    return () => {
      if (savedAnnouncement.current !== null) {
        savedAnnouncement.current.cancel()
        savedAnnouncement.current = null
        previousAnnouncementText.current = null
      }
    }
  }, [])

Just so we don't noop on duplicate announcements. What do you think @siddharthkp ?

@siddharthkp siddharthkp Oct 20, 2026 •

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.

Asked copilot to replace useEffectOnce with useEffect and reset previousAnnouncementText during cleanup. Hope this looks better?

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

This branch was successfully deployed

2 active deployments
storybook-preview-8528 — 96421986 Deployed Oct 20, 2026 by github-actions[bot]
github-pages — 96421986 Deployed Oct 20, 2026 by siddharthkp via deploy-preview #33770
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: failing Changes in this PR cause breaking changes in gh/gh staff Author is a staff member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants