From f4c7b83d434ca9c22afae8a1ce82feaf6563f71d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 16:57:59 +0000 Subject: [PATCH 01/12] Initial plan From 16ed8107b220d2bbdd5b1a23ac6d10773adc063e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 17:03:53 +0000 Subject: [PATCH 02/12] Initial commit - planning upgrade of eslint-plugin-primer-react Co-authored-by: siddharthkp <1863771+siddharthkp@users.noreply.github.com> --- package-lock.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index b0f35787c2f..6a7cf1b56e0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,7 +75,7 @@ "react-dom": "^18.3.1" }, "devDependencies": { - "@primer/react": "38.0.0-rc.8", + "@primer/react": "38.0.0-rc.9", "@types/react": "^18.3.11", "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.3.3", @@ -88,8 +88,8 @@ "name": "example-nextjs", "version": "0.0.0", "dependencies": { - "@primer/react": "38.0.0-rc.8", - "@primer/styled-react": "1.0.0-rc.9", + "@primer/react": "38.0.0-rc.9", + "@primer/styled-react": "1.0.0-rc.10", "next": "^15.2.3", "react": "18.3.1", "react-dom": "18.3.1", @@ -105,7 +105,7 @@ "version": "0.0.0", "dependencies": { "@primer/octicons-react": "^19.14.0", - "@primer/react": "38.0.0-rc.8", + "@primer/react": "38.0.0-rc.9", "clsx": "^2.1.1", "next": "^15.2.3", "react": "18.3.1", @@ -26317,7 +26317,7 @@ }, "packages/react": { "name": "@primer/react", - "version": "38.0.0-rc.8", + "version": "38.0.0-rc.9", "license": "MIT", "dependencies": { "@github/mini-throttle": "^2.1.1", @@ -26894,11 +26894,11 @@ }, "packages/styled-react": { "name": "@primer/styled-react", - "version": "1.0.0-rc.9", + "version": "1.0.0-rc.10", "devDependencies": { "@babel/preset-react": "^7.27.1", "@babel/preset-typescript": "^7.27.1", - "@primer/react": "^38.0.0-rc.8", + "@primer/react": "^38.0.0-rc.9", "@rollup/plugin-babel": "^6.0.4", "@types/react": "18.3.11", "@types/react-dom": "18.3.1", @@ -26914,7 +26914,7 @@ "typescript": "^5.9.2" }, "peerDependencies": { - "@primer/react": "38.0.0-rc.8", + "@primer/react": "38.0.0-rc.9", "@types/react": "18.x || 19.x", "@types/react-dom": "18.x || 19.x", "@types/react-is": "18.x || 19.x", From a4ddb52322ea498d0f8482810c6b0ab8f4023575 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 24 Oct 2025 17:21:21 +0000 Subject: [PATCH 03/12] Upgrade eslint-plugin-primer-react to v8.4.0 and enable spread-props-first rule Co-authored-by: siddharthkp <1863771+siddharthkp@users.noreply.github.com> --- eslint.config.mjs | 1 + package-lock.json | 8 ++-- package.json | 2 +- packages/react/src/ActionBar/ActionBar.tsx | 2 +- .../src/ActionList/ActionList.dev.stories.tsx | 4 +- .../ActionList.features.stories.tsx | 2 +- packages/react/src/ActionList/Group.tsx | 10 ++--- packages/react/src/ActionList/Heading.tsx | 4 +- packages/react/src/ActionList/Item.tsx | 4 +- packages/react/src/ActionList/LinkItem.tsx | 2 +- packages/react/src/ActionList/List.tsx | 2 +- .../react/src/ActionList/TrailingAction.tsx | 4 +- packages/react/src/ActionList/Visuals.tsx | 6 +-- packages/react/src/ActionMenu/ActionMenu.tsx | 6 +-- .../src/AnchoredOverlay/AnchoredOverlay.tsx | 8 ++-- .../Autocomplete.features.stories.tsx | 4 +- .../src/Autocomplete/Autocomplete.stories.tsx | 8 ++-- .../src/Autocomplete/Autocomplete.test.tsx | 4 +- .../src/Autocomplete/AutocompleteInput.tsx | 2 +- .../src/Autocomplete/AutocompleteMenu.tsx | 2 +- .../src/Autocomplete/AutocompleteOverlay.tsx | 2 +- packages/react/src/Avatar/Avatar.tsx | 2 +- packages/react/src/Banner/Banner.stories.tsx | 4 +- packages/react/src/Banner/Banner.tsx | 4 +- packages/react/src/BaseStyles.tsx | 4 +- .../react/src/Breadcrumbs/Breadcrumbs.tsx | 4 +- packages/react/src/Button/Button.tsx | 2 +- packages/react/src/Button/ButtonBase.tsx | 2 +- packages/react/src/Button/IconButton.tsx | 6 +-- packages/react/src/Button/LinkButton.tsx | 2 +- .../src/Button/__tests__/Button.test.tsx | 2 +- .../src/ButtonGroup/ButtonGroup.stories.tsx | 2 +- .../react/src/ButtonGroup/ButtonGroup.tsx | 2 +- .../react/src/Checkbox/Checkbox.stories.tsx | 2 +- .../react/src/CheckboxGroup/CheckboxGroup.tsx | 2 +- .../react/src/CircleBadge/CircleBadge.tsx | 2 +- .../ConfirmationDialog.stories.tsx | 2 +- packages/react/src/Details/Details.tsx | 4 +- .../src/Details/__tests__/Details.test.tsx | 2 +- packages/react/src/Dialog/Dialog.tsx | 16 ++++---- .../FilteredActionList/FilteredActionList.tsx | 13 ++++--- .../FilteredActionListLoaders.tsx | 2 +- .../FormControl.features.stories.tsx | 6 +-- packages/react/src/Header/Header.tsx | 6 +-- packages/react/src/Heading/Heading.tsx | 2 +- .../KeybindingHint/components/Sequence.tsx | 2 +- packages/react/src/Label/Label.tsx | 2 +- .../LabelGroup.features.stories.tsx | 2 +- .../src/LabelGroup/LabelGroup.stories.tsx | 2 +- packages/react/src/LabelGroup/LabelGroup.tsx | 2 +- packages/react/src/Link/Link.tsx | 2 +- .../src/NavList/NavList.features.stories.tsx | 4 +- packages/react/src/NavList/NavList.tsx | 6 +-- .../react/src/Octicon/Octicon.stories.tsx | 2 +- .../react/src/Overlay/Overlay.dev.stories.tsx | 2 +- .../react/src/Overlay/Overlay.stories.tsx | 2 +- packages/react/src/Overlay/Overlay.tsx | 18 ++++----- packages/react/src/PageHeader/PageHeader.tsx | 28 +++++++------- packages/react/src/PageLayout/PageLayout.tsx | 2 +- packages/react/src/Pagehead/Pagehead.tsx | 2 +- .../Pagination.features.stories.tsx | 2 +- .../src/Pagination/Pagination.stories.tsx | 2 +- .../react/src/Pagination/Pagination.test.tsx | 2 +- packages/react/src/Pagination/Pagination.tsx | 4 +- .../src/Pagination/mocks/ReactRouterLink.tsx | 2 +- packages/react/src/Popover/Popover.tsx | 2 +- .../react/src/ProgressBar/ProgressBar.tsx | 6 +-- packages/react/src/Radio/Radio.stories.tsx | 2 +- packages/react/src/Radio/Radio.tsx | 2 +- packages/react/src/RadioGroup/RadioGroup.tsx | 2 +- .../RelativeTime.features.stories.tsx | 6 +-- .../src/RelativeTime/RelativeTime.stories.tsx | 2 +- .../src/SegmentedControl/SegmentedControl.tsx | 8 ++-- .../SegmentedControlButton.tsx | 2 +- .../SegmentedControlIconButton.tsx | 6 +-- .../SelectPanel/SelectPanel.dev.stories.tsx | 12 +++--- .../SelectPanel.examples.stories.tsx | 18 ++++----- .../SelectPanel.features.stories.tsx | 38 +++++++++---------- .../src/SelectPanel/SelectPanel.stories.tsx | 2 +- .../src/SelectPanel/SelectPanel.test.tsx | 4 +- .../react/src/SelectPanel/SelectPanel.tsx | 6 +-- packages/react/src/SideNav.tsx | 2 +- packages/react/src/Skeleton/SkeletonBox.tsx | 2 +- .../src/SkeletonAvatar/SkeletonAvatar.tsx | 2 +- .../react/src/SkeletonText/SkeletonText.tsx | 4 +- packages/react/src/Spinner/Spinner.tsx | 2 +- .../src/SplitPageLayout/SplitPageLayout.tsx | 10 ++--- packages/react/src/Stack/Stack.tsx | 8 ++-- packages/react/src/SubNav/SubNav.tsx | 6 +-- packages/react/src/TabNav/TabNav.tsx | 2 +- packages/react/src/Text/Text.tsx | 2 +- .../TextInput/TextInput.features.stories.tsx | 24 ++++++------ .../react/src/TextInput/TextInput.stories.tsx | 2 +- packages/react/src/TextInput/TextInput.tsx | 2 +- .../TextInputWithTokens.test.tsx | 2 +- .../TextInputWithTokens.tsx | 4 +- packages/react/src/Textarea/Textarea.tsx | 2 +- .../react/src/ToggleSwitch/ToggleSwitch.tsx | 2 +- packages/react/src/Token/IssueLabelToken.tsx | 4 +- .../src/Token/Token.features.stories.tsx | 6 +-- packages/react/src/Token/Token.tsx | 4 +- packages/react/src/Token/TokenBase.tsx | 10 ++--- .../react/src/Token/_TokenTextContainer.tsx | 4 +- packages/react/src/Tooltip/Tooltip.tsx | 2 +- .../TooltipV2/Tooltip.playground.stories.tsx | 2 +- packages/react/src/TooltipV2/Tooltip.tsx | 2 +- .../src/TooltipV2/__tests__/Tooltip.test.tsx | 4 +- .../UnderlineNav.Item.stories.tsx | 2 +- .../react/src/UnderlineNav/UnderlineNav.tsx | 2 +- .../src/UnderlineNav/UnderlineNavItem.tsx | 2 +- .../src/VisuallyHidden/VisuallyHidden.tsx | 2 +- packages/react/src/_VisuallyHidden.tsx | 2 +- .../src/deprecated/ActionList/Header.tsx | 2 +- .../react/src/deprecated/ActionList/Item.tsx | 2 +- .../react/src/deprecated/ActionList/List.tsx | 2 +- packages/react/src/deprecated/ActionMenu.tsx | 2 +- .../react/src/deprecated/DialogV1/Dialog.tsx | 4 +- .../deprecated/UnderlineNav/UnderlineNav.tsx | 4 +- .../src/experimental/CSSComponent/index.tsx | 2 +- .../experimental/IssueLabel/IssueLabel.tsx | 2 +- .../experimental/SelectPanel2/SelectPanel.tsx | 16 ++++---- .../UnderlinePanels/UnderlinePanels.tsx | 6 +-- .../src/internal/components/ButtonReset.tsx | 2 +- .../CheckboxOrRadioGroup.tsx | 6 +-- .../src/internal/components/InputLabel.tsx | 2 +- .../components/TextInputInnerAction.tsx | 6 +-- .../internal/components/TextInputWrapper.tsx | 4 +- .../components/UnderlineTabbedInterface.tsx | 4 +- .../internal/components/UnstyledTextInput.tsx | 2 +- .../stories/deprecated/ActionList.stories.tsx | 10 ++--- .../stories/deprecated/ActionMenu.stories.tsx | 10 ++--- .../stories/useAnchoredPosition.stories.tsx | 8 ++-- .../src/stories/useFocusTrap.stories.tsx | 2 +- .../src/stories/useFocusZone.stories.tsx | 2 +- .../src/components/ActionList.tsx | 6 +-- .../styled-react/src/components/Avatar.tsx | 2 +- .../src/components/BaseStyles.tsx | 4 +- .../styled-react/src/components/Button.tsx | 2 +- .../styled-react/src/components/Checkbox.tsx | 2 +- .../src/components/CheckboxGroup.tsx | 8 ++-- .../src/components/CounterLabel.tsx | 2 +- .../styled-react/src/components/Dialog.tsx | 8 ++-- .../styled-react/src/components/Header.tsx | 3 ++ .../src/components/IconButton.tsx | 2 +- .../styled-react/src/components/NavList.tsx | 2 +- .../src/components/PageLayout.tsx | 3 ++ .../src/components/RadioGroup.tsx | 8 ++-- .../src/components/RelativeTime.tsx | 2 +- .../src/components/SegmentedControl.tsx | 6 +-- .../src/components/StateLabel.tsx | 2 +- .../styled-react/src/components/SubNav.tsx | 4 +- .../styled-react/src/components/TextInput.tsx | 2 +- .../styled-react/src/components/Timeline.tsx | 10 ++--- .../src/components/ToggleSwitch.tsx | 2 +- .../styled-react/src/components/Tooltip.tsx | 2 +- .../src/components/UnderlineNav.tsx | 2 +- .../src/components/UnderlinePanels.tsx | 2 +- .../src/components/deprecated/ActionList.tsx | 6 +-- .../src/components/deprecated/DialogV1.tsx | 2 + 159 files changed, 360 insertions(+), 350 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 6e0f2b9a7a6..79ca8268452 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -117,6 +117,7 @@ const config = defineConfig([ 'primer-react/a11y-use-next-tooltip': 'error', 'primer-react/no-unnecessary-components': 'error', 'primer-react/prefer-action-list-item-onselect': 'error', + 'primer-react/spread-props-first': 'error', }, }, diff --git a/package-lock.json b/package-lock.json index 6a7cf1b56e0..8cdcd449b5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,7 +40,7 @@ "eslint-plugin-mdx": "3.6.2", "eslint-plugin-playwright": "^2.2.2", "eslint-plugin-prettier": "^5.5.4", - "eslint-plugin-primer-react": "^8.2.0", + "eslint-plugin-primer-react": "^8.4.0", "eslint-plugin-react": "^7.35.5", "eslint-plugin-react-compiler": "^19.1.0-rc.2", "eslint-plugin-react-hooks": "^5.2.0", @@ -12668,9 +12668,9 @@ } }, "node_modules/eslint-plugin-primer-react": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-primer-react/-/eslint-plugin-primer-react-8.2.0.tgz", - "integrity": "sha512-+uz0T1qyfRhMavojoATVrLBdQ/JoX7XMc6BMowCBtB+M+AerrW8lXj9pVUViMe35Iaw+3eRMHAdXHho82BYyvw==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-primer-react/-/eslint-plugin-primer-react-8.4.0.tgz", + "integrity": "sha512-lReoFdF1IuZ7vJQTC8IzFo/xuzDkz15DCbm0zWeL18HxIPRRWEb1JP9oDwlejaiqCF6VFfQ4fef7u7zBhGALVQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 5bad61cd66e..244da076231 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "eslint-plugin-mdx": "3.6.2", "eslint-plugin-playwright": "^2.2.2", "eslint-plugin-prettier": "^5.5.4", - "eslint-plugin-primer-react": "^8.2.0", + "eslint-plugin-primer-react": "^8.4.0", "eslint-plugin-react": "^7.35.5", "eslint-plugin-react-compiler": "^19.1.0-rc.2", "eslint-plugin-react-hooks": "^5.2.0", diff --git a/packages/react/src/ActionBar/ActionBar.tsx b/packages/react/src/ActionBar/ActionBar.tsx index 7046dc44984..3ce7d9ff414 100644 --- a/packages/react/src/ActionBar/ActionBar.tsx +++ b/packages/react/src/ActionBar/ActionBar.tsx @@ -408,11 +408,11 @@ export const ActionBarIconButton = forwardRef( return ( diff --git a/packages/react/src/ActionList/ActionList.dev.stories.tsx b/packages/react/src/ActionList/ActionList.dev.stories.tsx index ec560222be0..2b14654deab 100644 --- a/packages/react/src/ActionList/ActionList.dev.stories.tsx +++ b/packages/react/src/ActionList/ActionList.dev.stories.tsx @@ -334,7 +334,7 @@ export const OverlayWrapping = () => { ( - )} @@ -350,7 +350,7 @@ export const OverlayWrapping = () => { open width="small" renderAnchor={props => ( - )} diff --git a/packages/react/src/ActionList/ActionList.features.stories.tsx b/packages/react/src/ActionList/ActionList.features.stories.tsx index e7ff8b11f50..27ab410451b 100644 --- a/packages/react/src/ActionList/ActionList.features.stories.tsx +++ b/packages/react/src/ActionList/ActionList.features.stories.tsx @@ -711,7 +711,7 @@ export const InsideOverlay = () => { onOpen={toggle} onClose={toggle} renderAnchor={props => ( - )} diff --git a/packages/react/src/ActionList/Group.tsx b/packages/react/src/ActionList/Group.tsx index 441e79302c9..b51afebfa67 100644 --- a/packages/react/src/ActionList/Group.tsx +++ b/packages/react/src/ActionList/Group.tsx @@ -24,13 +24,13 @@ const Heading: React.FC> ...rest }) => { return ( - + {children} ) } -type HeadingWrapProps = { +type HeadingWrapProps = React.HTMLAttributes & { as?: 'div' | 'li' className?: string children: React.ReactNode @@ -98,7 +98,7 @@ export const Group: FCWithSlotMarker +
  • {title && !slots.groupHeading ? ( // Escape hatch: supports old API in a non breaking way @@ -173,13 +173,13 @@ export const GroupHeading: FCWithSlotMarker