Skip to content

docs: add prop merging ADR and adoption tooling - #8248

Open
joshblack with Copilot wants to merge 12 commits into
mainfrom
copilot/update-style-docs-prop-merging
Open

docs: add prop merging ADR and adoption tooling#8248
joshblack with Copilot wants to merge 12 commits into
mainfrom
copilot/update-style-docs-prop-merging

Conversation

Copilot AI commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Closes #

This PR adds ADR-025 and the foundation for adopting one prop-merging convention across Primer React. This entry owns the shared utility, deterministic ESLint rule, migration report, workflow integration, and future refinements to those tools.

Changelog

New

  • Add ADR-025 and the internal mergeProps utility.
  • Add the local ESLint rule and migration-status reporting for component root prop spreads.

Changed

  • Refine reporting to ignore pure prop-forwarding wrappers that have no component-authored props to merge.

Removed

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

This is internal architecture and migration tooling. mergeProps is not exported as public API, and component behavior changes will be reviewed in separate batch entries.

Testing & Reviewing

Please review the ADR contract, merge semantics, and the boundary used by primer/prefer-merge-props. In particular, pure forwarding wrappers should not appear in the report, while roots combining authored and consumer props should remain findings.

@changeset-bot

changeset-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 1bc6f64

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

@joshblack joshblack added the skip changeset This change does not need a changelog label Jul 28, 2026 — with Copilot SWE Agent
Copilot AI requested a review from joshblack July 28, 2026 20:14

@joshblack joshblack left a comment

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.

@copilot add the mergeProps.ts utility from: https://github.com/primer/react/pull/8168/changes#diff-b21bbbcb2674bcbc6f8e205e1c9223efea602c2abea46bb150c1d34b8ee06d07 and include tests for it. Also add an ADR for prop merging conventions for me with this decision. Highlight any scenarios that I should be aware of that aren't included already

Copilot AI commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot add the mergeProps.ts utility from: https://github.com/primer/react/pull/8168/changes#diff-b21bbbcb2674bcbc6f8e205e1c9223efea602c2abea46bb150c1d34b8ee06d07 and include tests for it. Also add ...

Implemented in ba4584c. Added mergeProps with tests, ADR-025, and updated the style guide to use the utility. The ADR highlights refs, shallow style merging, defaultPrevented/stopPropagation, synchronous one-way cancellation, thrown errors, on* callback detection, zero- and multi-argument callbacks, and explicit undefined precedence.

Copilot AI requested a review from joshblack July 28, 2026 21:23
@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 Jul 28, 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.

Comment thread contributor-docs/style.md Outdated
Comment thread contributor-docs/adrs/adr-025-prop-merging.md Outdated

@joshblack joshblack left a comment

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.

@copilot I want to create an eslint rule for this behavior. To do this, let's:

  • Create a local @primer/eslint-config private package in packages/*
  • In this, add a rule for the proposed merge props behavior
  • This rule should look to see if props are spread on the outermost element and prefer using mergeProps
  • This rule should not be enabled by default (eventually we will turn it on)
  • Add a new migration report for this rule, reporting on number of places where it is failing that we would need to migrate


The general rules do not cover every form of composition:

- **Refs are not composed.** Use `useMergedRefs` when both the component and

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.

@copilot add a note that this will change in React 19 with refs passed as props

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Documented the React 19 ref-as-prop behavior and clarified that refs still require separate composition in 01b40e1.

Copilot AI requested a review from joshblack July 30, 2026 16:11
@github-actions
github-actions Bot temporarily deployed to storybook-preview-8248 July 30, 2026 16:14 Inactive
@github-actions
github-actions Bot requested a deployment to storybook-preview-8248 July 30, 2026 16:19 Abandoned
@github-actions
github-actions Bot temporarily deployed to storybook-preview-8248 July 30, 2026 16:28 Inactive
@github-actions
github-actions Bot temporarily deployed to storybook-preview-8248 July 30, 2026 16:39 Inactive
@joshblack
joshblack force-pushed the copilot/update-style-docs-prop-merging branch from c163b71 to fc7d2ac Compare July 30, 2026 17:01
@github-actions
github-actions Bot temporarily deployed to storybook-preview-8248 July 30, 2026 17:11 Inactive
Copilot AI and others added 12 commits July 31, 2026 13:25
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Co-authored-by: joshblack <3901764+joshblack@users.noreply.github.com>
Ignore pure prop-forwarding wrappers so the adoption report only tracks component roots with props that need intentional merging.

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

Copilot-Session: 00bfd295-6ed9-4119-8d63-103a0b3c63e8
@joshblack
joshblack force-pushed the copilot/update-style-docs-prop-merging branch from fc7d2ac to 1bc6f64 Compare July 31, 2026 18:35
@joshblack joshblack mentioned this pull request Jul 31, 2026
4 tasks
@@ -0,0 +1,278 @@
import {ASTUtils, type TSESLint, type TSESTree} from '@typescript-eslint/utils'

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.

curious on the decision to create a new package for this rule over adding to https://github.com/primer/eslint-plugin-primer-react 👀

type EventHandler = (...args: unknown[]) => void
type ClassValue = Parameters<typeof clsx>[number]

function mergeProps<A extends object, B extends object = A>(a: A, b: B): Merge<A, B> {

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.

would be nice to have docs here at the top explaining functionality/precedence

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 integration-tests: skipped manually Changes in this PR do not require an integration test skip changeset This change does not need a changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants