From da5ac265195b64fa3c61cb68c8ae01a54883e435 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 17 Jun 2026 12:45:46 +0000
Subject: [PATCH 1/2] Initial plan
From 57e358d067336f4c8a5427ff6bf30f8ae665ab8a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 17 Jun 2026 12:55:23 +0000
Subject: [PATCH 2/2] perf(css): make ButtonGroup, Pagination, Checkbox
selectors bucketable
Co-authored-by: mattcosta7 <8616962+mattcosta7@users.noreply.github.com>
---
.changeset/perf-css-bucketable-selectors.md | 5 +++
.../src/ButtonGroup/ButtonGroup.module.css | 2 +-
.../react/src/ButtonGroup/ButtonGroup.tsx | 6 +++-
.../react/src/Checkbox/Checkbox.module.css | 33 ++++++++++---------
.../react/src/DataTable/Pagination.module.css | 21 +++++++-----
5 files changed, 41 insertions(+), 26 deletions(-)
create mode 100644 .changeset/perf-css-bucketable-selectors.md
diff --git a/.changeset/perf-css-bucketable-selectors.md b/.changeset/perf-css-bucketable-selectors.md
new file mode 100644
index 00000000000..2b1ac139a08
--- /dev/null
+++ b/.changeset/perf-css-bucketable-selectors.md
@@ -0,0 +1,5 @@
+---
+'@primer/react': patch
+---
+
+Improve style-recalc performance by making ButtonGroup, DataTable Pagination, and Checkbox CSS selectors bucketable (removing universal `*`/`:not([attr])` subjects and `:is()` selector-list merges)
diff --git a/packages/react/src/ButtonGroup/ButtonGroup.module.css b/packages/react/src/ButtonGroup/ButtonGroup.module.css
index cb942aef85c..9c681a324c0 100644
--- a/packages/react/src/ButtonGroup/ButtonGroup.module.css
+++ b/packages/react/src/ButtonGroup/ButtonGroup.module.css
@@ -3,7 +3,7 @@
vertical-align: middle;
isolation: isolate;
- & > *:not([data-loading-wrapper]) {
+ & > .Item {
/* stylelint-disable-next-line primer/spacing */
margin-inline-end: -1px;
position: relative;
diff --git a/packages/react/src/ButtonGroup/ButtonGroup.tsx b/packages/react/src/ButtonGroup/ButtonGroup.tsx
index 1bf04bb3278..7fa12fad872 100644
--- a/packages/react/src/ButtonGroup/ButtonGroup.tsx
+++ b/packages/react/src/ButtonGroup/ButtonGroup.tsx
@@ -16,7 +16,11 @@ const ButtonGroup = React.forwardRef(function ButtonGroup(
{as: BaseComponent = 'div', children, className, role, ...rest},
forwardRef,
) {
- const buttons = React.Children.map(children, (child, index) =>
{child}
)
+ const buttons = React.Children.map(children, (child, index) => (
+
+ {child}
+
+ ))
const buttonRef = useProvidedRefOrCreate(forwardRef as React.RefObject)
useFocusZone({
diff --git a/packages/react/src/Checkbox/Checkbox.module.css b/packages/react/src/Checkbox/Checkbox.module.css
index 2be4bc11d95..26e48109d40 100644
--- a/packages/react/src/Checkbox/Checkbox.module.css
+++ b/packages/react/src/Checkbox/Checkbox.module.css
@@ -30,21 +30,6 @@
/* stylelint-disable-next-line primer/colors */
border-color: var(--control-checked-bgColor-rest);
- &::before {
- animation: checkmarkIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;
- }
-
- &:disabled {
- background-color: var(--control-checked-bgColor-disabled);
- border-color: var(--control-checked-borderColor-disabled);
- opacity: 1;
-
- &::before {
- /* stylelint-disable-next-line primer/colors */
- background-color: var(--control-checked-fgColor-disabled);
- }
- }
-
/* Windows High Contrast mode */
@media (forced-colors: active) {
background-color: canvastext;
@@ -52,6 +37,24 @@
}
}
+ &:checked::before,
+ &:indeterminate::before {
+ animation: checkmarkIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;
+ }
+
+ &:checked:disabled,
+ &:indeterminate:disabled {
+ background-color: var(--control-checked-bgColor-disabled);
+ border-color: var(--control-checked-borderColor-disabled);
+ opacity: 1;
+ }
+
+ &:checked:disabled::before,
+ &:indeterminate:disabled::before {
+ /* stylelint-disable-next-line primer/colors */
+ background-color: var(--control-checked-fgColor-disabled);
+ }
+
&:disabled {
cursor: not-allowed;
}
diff --git a/packages/react/src/DataTable/Pagination.module.css b/packages/react/src/DataTable/Pagination.module.css
index e56f7f787b2..e2f54ecaabb 100644
--- a/packages/react/src/DataTable/Pagination.module.css
+++ b/packages/react/src/DataTable/Pagination.module.css
@@ -13,43 +13,46 @@
}
@media ((max-width: calc(768px - 0.02px))) {
- .TablePaginationSteps[data-hidden-viewport-ranges*='narrow'] > *:not(:first-child):not(:last-child) {
+ /* stylelint-disable-next-line selector-max-specificity -- li type subject keeps the selector bucketable for style-recalc perf (github/github-ui#23654) */
+ .TablePaginationSteps[data-hidden-viewport-ranges*='narrow'] > li:not(:first-child):not(:last-child) {
display: none;
}
- .TablePaginationSteps[data-hidden-viewport-ranges*='narrow'] > *:first-child {
+ .TablePaginationSteps[data-hidden-viewport-ranges*='narrow'] > li:first-child {
margin-inline-end: 0;
}
- .TablePaginationSteps[data-hidden-viewport-ranges*='narrow'] > *:last-child {
+ .TablePaginationSteps[data-hidden-viewport-ranges*='narrow'] > li:last-child {
margin-inline-start: 0;
}
}
@media ((min-width: 768px)) {
- .TablePaginationSteps[data-hidden-viewport-ranges*='regular'] > *:not(:first-child):not(:last-child) {
+ /* stylelint-disable-next-line selector-max-specificity -- li type subject keeps the selector bucketable for style-recalc perf (github/github-ui#23654) */
+ .TablePaginationSteps[data-hidden-viewport-ranges*='regular'] > li:not(:first-child):not(:last-child) {
display: none;
}
- .TablePaginationSteps[data-hidden-viewport-ranges*='regular'] > *:first-child {
+ .TablePaginationSteps[data-hidden-viewport-ranges*='regular'] > li:first-child {
margin-inline-end: 0;
}
- .TablePaginationSteps[data-hidden-viewport-ranges*='regular'] > *:last-child {
+ .TablePaginationSteps[data-hidden-viewport-ranges*='regular'] > li:last-child {
margin-inline-start: 0;
}
}
@media ((min-width: 1400px)) {
- .TablePaginationSteps[data-hidden-viewport-ranges*='wide'] > *:not(:first-child):not(:last-child) {
+ /* stylelint-disable-next-line selector-max-specificity -- li type subject keeps the selector bucketable for style-recalc perf (github/github-ui#23654) */
+ .TablePaginationSteps[data-hidden-viewport-ranges*='wide'] > li:not(:first-child):not(:last-child) {
display: none;
}
- .TablePaginationSteps[data-hidden-viewport-ranges*='wide'] > *:first-child {
+ .TablePaginationSteps[data-hidden-viewport-ranges*='wide'] > li:first-child {
margin-inline-end: 0;
}
- .TablePaginationSteps[data-hidden-viewport-ranges*='wide'] > *:last-child {
+ .TablePaginationSteps[data-hidden-viewport-ranges*='wide'] > li:last-child {
margin-inline-start: 0;
}
}