From 48d8117cdd6eb87fe69d0545d6815e9d47026210 Mon Sep 17 00:00:00 2001 From: Reza Rahman <13340707+rezrah@users.noreply.github.com> Date: Mon, 17 Aug 2026 16:00:20 +0100 Subject: [PATCH 1/2] backfill missing control tokens --- .changeset/fix-esm-functional-size-tokens.md | 5 +++++ .github/workflows/integration_test_nextjs.yml | 2 ++ .../integration-tests/nextjs/button-only/page.tsx | 7 +++++++ .../integration-tests/tests/check-warnings.cy.ts | 14 ++++++++++++++ packages/react/src/css/stylesheets.ts | 2 ++ 5 files changed, 30 insertions(+) create mode 100644 .changeset/fix-esm-functional-size-tokens.md create mode 100644 packages/e2e/integration-tests/nextjs/button-only/page.tsx diff --git a/.changeset/fix-esm-functional-size-tokens.md b/.changeset/fix-esm-functional-size-tokens.md new file mode 100644 index 0000000000..6b07ddebaf --- /dev/null +++ b/.changeset/fix-esm-functional-size-tokens.md @@ -0,0 +1,5 @@ +--- +'@primer/react-brand': patch +--- + +Fixed missing size and animation tokens in tree-shaken ESM component bundles like `Button`. Now all control tokens are loaded globally as a side-effect. diff --git a/.github/workflows/integration_test_nextjs.yml b/.github/workflows/integration_test_nextjs.yml index 7da9767d58..8d5f0e844e 100644 --- a/.github/workflows/integration_test_nextjs.yml +++ b/.github/workflows/integration_test_nextjs.yml @@ -96,6 +96,8 @@ jobs: run: | rm ./${{ env.NEXTJS_FOLDER }}/app/page.tsx cp ./packages/e2e/integration-tests/nextjs/page.tsx ./${{ env.NEXTJS_FOLDER }}/app + mkdir ./${{ env.NEXTJS_FOLDER }}/app/button-only + cp ./packages/e2e/integration-tests/nextjs/button-only/page.tsx ./${{ env.NEXTJS_FOLDER }}/app/button-only cp ./packages/e2e/cypress.config.js ./${{ env.NEXTJS_FOLDER }} mkdir ${{ env.NEXTJS_FOLDER }}/integration-tests cp -r ./packages/e2e/integration-tests/fixtures ./${{ env.NEXTJS_FOLDER }}/integration-tests diff --git a/packages/e2e/integration-tests/nextjs/button-only/page.tsx b/packages/e2e/integration-tests/nextjs/button-only/page.tsx new file mode 100644 index 0000000000..34d39d4e29 --- /dev/null +++ b/packages/e2e/integration-tests/nextjs/button-only/page.tsx @@ -0,0 +1,7 @@ +'use client' + +import {Button} from '../../integration-tests/fixtures' + +export default function ButtonOnlyPage() { + return +} diff --git a/packages/e2e/integration-tests/tests/check-warnings.cy.ts b/packages/e2e/integration-tests/tests/check-warnings.cy.ts index 6e43d69184..f892ebe1a2 100644 --- a/packages/e2e/integration-tests/tests/check-warnings.cy.ts +++ b/packages/e2e/integration-tests/tests/check-warnings.cy.ts @@ -24,4 +24,18 @@ describe('Integration tests', () => { expect(windowWarningSpy).to.not.be.called }) }) + + it('loads shared size tokens without Stack on the page', () => { + cy.visit('http://localhost:3000/button-only') + + cy.get('[data-testid="button-only"]').should(button => { + const ownerWindow = button[0].ownerDocument.defaultView + + if (!ownerWindow) throw new Error('Expected the Button document to have a window') + + const controlSize = ownerWindow.getComputedStyle(button[0]).getPropertyValue('--brand-control-medium-size').trim() + + expect(controlSize).not.to.equal('') + }) + }) }) diff --git a/packages/react/src/css/stylesheets.ts b/packages/react/src/css/stylesheets.ts index 9bdb631d3f..30040dcb47 100644 --- a/packages/react/src/css/stylesheets.ts +++ b/packages/react/src/css/stylesheets.ts @@ -9,6 +9,8 @@ import './reset.css' import '@primer/brand-primitives/lib/design-tokens/css/tokens/base/colors/color-scales-with-modes.css' import '@primer/brand-primitives/lib/design-tokens/css/tokens/base/size/size.css' import '@primer/brand-primitives/lib/design-tokens/css/tokens/base/typography/typography.css' +import '@primer/brand-primitives/lib/design-tokens/css/tokens/functional/animation/base.css' +import '@primer/brand-primitives/lib/design-tokens/css/tokens/functional/size/size.css' import '@primer/brand-primitives/lib/design-tokens/css/tokens/functional/typography/typography-responsive.css' import '@primer/brand-primitives/lib/design-tokens/css/tokens/functional/size/breakpoints.css' import '@primer/brand-primitives/lib/design-tokens/css/tokens/functional/size/border.css' From cf3aa2184ac5f09f3879f7945f55677be4eca473 Mon Sep 17 00:00:00 2001 From: Reza Rahman <13340707+rezrah@users.noreply.github.com> Date: Wed, 19 Aug 2026 11:49:29 +0100 Subject: [PATCH 2/2] move esm fixture to correct folder --- .github/workflows/integration_test_nextjs.yml | 1 + .../nextjs/check-size-tokens.cy.ts | 15 +++++++++++++++ .../integration-tests/tests/check-warnings.cy.ts | 14 -------------- 3 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 packages/e2e/integration-tests/nextjs/check-size-tokens.cy.ts diff --git a/.github/workflows/integration_test_nextjs.yml b/.github/workflows/integration_test_nextjs.yml index 8d5f0e844e..5cd0115a61 100644 --- a/.github/workflows/integration_test_nextjs.yml +++ b/.github/workflows/integration_test_nextjs.yml @@ -102,6 +102,7 @@ jobs: mkdir ${{ env.NEXTJS_FOLDER }}/integration-tests cp -r ./packages/e2e/integration-tests/fixtures ./${{ env.NEXTJS_FOLDER }}/integration-tests cp -r ./packages/e2e/integration-tests/tests ./${{ env.NEXTJS_FOLDER }}/integration-tests + cp ./packages/e2e/integration-tests/nextjs/check-size-tokens.cy.ts ./${{ env.NEXTJS_FOLDER }}/integration-tests/tests - name: Excluded cypress tests in-place # includes temp workaround for cypress bug. remove when fixed diff --git a/packages/e2e/integration-tests/nextjs/check-size-tokens.cy.ts b/packages/e2e/integration-tests/nextjs/check-size-tokens.cy.ts new file mode 100644 index 0000000000..9dd403c8bc --- /dev/null +++ b/packages/e2e/integration-tests/nextjs/check-size-tokens.cy.ts @@ -0,0 +1,15 @@ +describe('Size token integration tests', () => { + it('loads shared size tokens without Stack on the page', () => { + cy.visit('http://localhost:3000/button-only') + + cy.get('[data-testid="button-only"]').should(button => { + const ownerWindow = button[0].ownerDocument.defaultView + + if (!ownerWindow) throw new Error('Expected the Button document to have a window') + + const controlSize = ownerWindow.getComputedStyle(button[0]).getPropertyValue('--brand-control-medium-size').trim() + + expect(controlSize).not.to.equal('') + }) + }) +}) diff --git a/packages/e2e/integration-tests/tests/check-warnings.cy.ts b/packages/e2e/integration-tests/tests/check-warnings.cy.ts index f892ebe1a2..6e43d69184 100644 --- a/packages/e2e/integration-tests/tests/check-warnings.cy.ts +++ b/packages/e2e/integration-tests/tests/check-warnings.cy.ts @@ -24,18 +24,4 @@ describe('Integration tests', () => { expect(windowWarningSpy).to.not.be.called }) }) - - it('loads shared size tokens without Stack on the page', () => { - cy.visit('http://localhost:3000/button-only') - - cy.get('[data-testid="button-only"]').should(button => { - const ownerWindow = button[0].ownerDocument.defaultView - - if (!ownerWindow) throw new Error('Expected the Button document to have a window') - - const controlSize = ownerWindow.getComputedStyle(button[0]).getPropertyValue('--brand-control-medium-size').trim() - - expect(controlSize).not.to.equal('') - }) - }) })