Repository navigation
Update @wordpress/components from 28 to 41 as the base for the design system redesign - #563
Merged
Merged
Conversation
…10 to 17 First step of the WordPress Design System redesign (#542): @wordpress/ui and @wordpress/theme are built against the current components release, so the renderer has to stand on it before either can be added. The `edit` icon no longer exists in @wordpress/icons 17; `pencil` is the same glyph under its current name. The sidebar title is kept on one line: buttons are set in a heavier weight now, and the wider "Collapse" button wrapped "Contributor Toolkit" onto two lines. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d app @wordpress/components 41 depends on @wordpress/ui and @wordpress/theme, and @wordpress/theme names esbuild as an optional peer. npm therefore stopped marking esbuild as dev-only, and electron-builder, which collects optional packages, started shipping its binary along with twelve other packages the update added. None of them is loaded at run time: the renderer is the esbuild bundle, and nothing under src/ requires them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: WordPress/contributor-toolkit/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
zaerl
added a commit
that referenced
this pull request
Sep 30, 2026
…ns at the renderer's root (#564) ## Why The redesign in #542 styles the app with the WordPress Design System's tokens and builds its new screens from `@wordpress/ui`. Neither is available to the renderer yet: the tokens stylesheet is not loaded, so a `var(--wpds-…)` written in the app resolves to nothing, and there is no provider to set colour or corner radius from. This is the second step of #542, after #563. ## What changes - `@wordpress/theme` and `@wordpress/ui` become dependencies of the app. Both were already installed through `@wordpress/components` 41, so no package is new to the tree. - The renderer imports `@wordpress/theme/design-tokens.css` and mounts inside `<ThemeProvider isRoot>` at its defaults. `isRoot` is what lets a later override reach a modal or a popover, which are portalled to `body`, outside the provider's tree. - The next-action live region uses `VisuallyHidden` from `@wordpress/ui`, and the hand-written `.sr-only` rule is removed. This is the one use of `@wordpress/ui`, and it is here on purpose: the package adds its styles to the document at run time, and this makes that path run in the app and not only in the bundle. - `@wordpress/theme` joins the packages kept out of the packaged app. It is hoisted to the top of `node_modules` now that the app depends on it, where the exclusion of `@wordpress/ui` from #563 no longer covers it. Deliberately not in this PR: any colour or corner radius set on the provider, any use of a token in the app's own styles, any new `@wordpress/ui` component. The 333 hardcoded colours stay where they are until their own step. ## How to test this Platforms: any. Use the Buildkite build for the current head of this branch. The launch journey carries this. `npx playwright test --project=journeys -g "launches from source"`, from the repository root, asserts that a token resolves, that the provider's wrapper and the live region have the styles added at run time, and that the app rendered inside the provider. It is red without the tokens import, red without `'unsafe-inline'` in the window's style policy, red when the app renders nothing, and red when the live region is a plain element; each was checked by breaking it. What the journey cannot reach is how it looks and how it sounds: **Starting state:** the app open with at least one site that has finished setup and whose dev server is stopped. 1. Look at "Start dev server" and "Create a site". The labels are readable on the blue; they are very slightly off-white, not pure white. 2. Press Tab until a button has the focus ring. The ring is visible and thinner than before on a high-density screen. 3. Collapse and expand the sidebar, open "Create a site", open the site's menu. The layout is as it was. 4. With a screen reader running, open the site. It announces "Next step:" followed by the step. **What must not have happened:** - No text reading "Next step: …" is visible anywhere on the page. - The window has not lost its full-height layout: the sidebar still reaches the bottom. ## Risks and limitations - **Two things change on screen, and only two.** With the tokens defined, the components stop using fallbacks that only approximated them: a primary button's label is `#eff0f2` rather than `#fff`, and the focus ring is 1.5px rather than 2px on a high-density screen. The second is read from the stylesheet; the screenshots are captured at 1x and cannot show it. - **The screen reader was not tried.** The live region keeps its role, its `aria-live` and its text, all asserted by the journey, but nobody listened to it. - **Checked on macOS only by hand and by local runs.** Windows is covered by CI's journeys and packaged smoke. - **The renderer bundle grows** by about 179 KB of JavaScript and 10 KB of CSS. The packaged app does not: 199,750,409 bytes of `app.asar` against 199,873,553 before. - Review: 3 [fix here], all low and all in the tests, all fixed. ## Related Closes #549 Part of #542. Follows #563. --- <details> <summary>Design decisions and alternatives considered</summary> **The provider at its defaults, not at the prototype's settings.** The prototype sets `cornerRadius="moderate"` and its own colour seeds. Setting them here would round every existing control while the rest of the app still has the old layout. They belong with the shell. **One real use of `@wordpress/ui` rather than none.** Declaring the dependency with nothing importing it would have left its run-time styles untested until the first screen built on them. `VisuallyHidden` replaces a rule the app had written by hand, changes nothing on screen, and is enough to show that the window's content security policy lets those styles in. **No build plugin for token fallbacks.** `@wordpress/theme` ships an esbuild plugin that writes a fallback into every `var(--wpds-…)`. The app loads the tokens stylesheet itself, in the one document it has, so there is nothing for a fallback to cover. </details> <details> <summary>Review outcome (required — see AGENTS.md)</summary> **3 [fix here] · 0 [follow-up]** — all 3 fixed. - Tests, low, [fix here], fixed: `#root > *` in the launch journey and the packaged smoke test was the proof that the app painted; the provider is now always that child, so it passed with nothing inside. Both look at `#root > * > *`. - Tests, low, [fix here], fixed: the live region was found by `[data-visually-hidden]`, which `@wordpress/components` also puts on its own hidden text with inline styles, so the first match could pass with no injected style. It is found by role and by what it says, and its `aria-live` is asserted. - Tests, low, [fix here], fixed: the design system's checks were a test of their own and cost an app launch on every pull request. They moved into the launch test. Style note, applied: a comment said the tokens import had to come before the components' stylesheet. The order does not matter. - **Review:** completed — fresh agent context, local, before the PR existed; head 47b8827 / base f6930f3; committed work only, working tree clean; outcome above. CodeRabbit: not run yet. - **Since review:** `47b8827 → 6fdf0d0` checked. The difference is the three fixes and the comment. It was not reviewed again by a fresh context; it was verified by the runs below and by breaking each assertion in turn. Checks on 6fdf0d0, macOS, local: | Check | Result | |---|---| | `npm run lint` | clean | | `npm test` | 1674 pass, 2 skipped, 0 fail | | `npm run test:electron` | 1676 pass, 0 fail | | `npm run test:e2e` | 33 of 33 pass | | `npm run test:e2e:packaged` | 15 of 15 pass | </details> <details> <summary>Implementation notes</summary> `ThemeProvider` renders a wrapper `<div>` with `display: contents`, so it takes no part in the layout. That rule, like every style in `@wordpress/theme` and `@wordpress/ui`, is added to the document as a `<style>` element when the module loads. The window's policy is `style-src 'self' 'unsafe-inline'`, which allows it; the journey is what notices if that ever changes. How the two on-screen changes were found: every `var(--wpds-…, fallback)` in the components' stylesheet was compared with the value the tokens stylesheet now gives it. 50 of 57 pairs are equal, 3 fall back to a variable holding the same value, and 3 only differ under a corner radius preset the provider does not set. The remaining one is the primary button's label colour. The focus ring's 1.5px comes from a media query for high-density screens in the tokens stylesheet. </details> <details> <summary>Screenshots or recording</summary> No images attached. The twelve shots `npm run shots` captures were taken on `trunk` and on this branch and compared pixel by pixel. Six are identical. Four differ only on primary buttons, by at most 16 levels per channel, which is the label colour above. The last two, `site-menu` and `gutenberg-site-view`, also differ between two runs on `trunk`, so they show nothing either way. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Merged
zaerl
added a commit
that referenced
this pull request
Oct 23, 2026
…braries and Chromium locales (#707) ## Why The packaged app is about 920 MB on disk on macOS (320 MB zipped), and about a third of that is code it never loads. That is a long download on a Contributor Day network, where everyone fetches the app at the same time. It is the same problem #23 reported. That PR has since gone stale against trunk, and its claim that `@xterm/xterm` is unused no longer holds, so this branch starts again from trunk. ## What changes Three things the app ships and never loads are left out: - **The asyncify PHP builds, about 220 MB.** Each `@php-wasm/node-*` package carries every PHP version twice, as `jspi/` and as `asyncify/`, and `@php-wasm/node` reads `asyncify/` only when `"Suspending" in WebAssembly` is false. Electron 43.6.0 has JSPI, so those folders never load. `@php-wasm/node-5-2` goes too, because the app offers only `SupportedPHPVersions` (7.4–8.5). Both are `build.files` exclusions; `node_modules` is untouched. - **The renderer's libraries, about 95 MB in `app.asar`.** esbuild already bundles React, Emotion, xterm and the `@wordpress` UI packages into `src/renderer/index.js`, but they were listed in `dependencies`, so electron-builder copied their trees in as well. They move to `devDependencies`. `@wordpress/i18n` and `@wordpress/hooks` stay, because the main process loads them. The 22 hand-kept `build.files` exclusions that trimmed part of that tree since #563 are now unnecessary and are removed. - **Chromium's locales for languages the app has no catalog for, about 43 MB.** The app shows English for those anyway, so `build.electronLanguages` keeps English and the Chromium locale of each catalog in `src/languages`. **`npm run i18n:download` now writes that list** whenever it adds or removes a catalog, so the version-bump PR carries the change with no manual step. `scripts/chromium-locales.cjs` maps a catalog to the locale Chromium itself would load, including Chromium's regional folding (`es-mx` → `es-419`, `pt` → `pt-PT`, `zh-hk` → `zh-TW`, `en-ca` → `en-GB`). Every regional locale is written in both spellings, `pt-BR` for Windows and Linux and `pt_BR` for macOS, because electron-builder matches file names. Unit tests guard the cuts: - `electron-wasm-jspi` asks the bundled Electron for `WebAssembly.Suspending`, so an Electron bump that loses JSPI fails CI instead of the first dev server start. - `electron-languages` asserts that the list equals the one the catalogs call for, which catches both a missing entry and a stale one. It also checks that electron-builder keeps every locale file the list names. - `chromium-locales` covers the mapping with both platforms' locale names. - `php-builds` fails when an installed `@php-wasm/node-X-Y` whose version `SupportedPHPVersions` does not offer would ship, and when a version the settings offer is excluded. Run against translate.wordpress.org today, the script adds `sr` and `tr` for two catalogs that are above the cut-off but not yet in the repository, and leaves out `lo`, which Chromium has no locale for. Not in this PR: dropping PHP versions the settings offer (a product decision since #559), and the `intl` extension and ICU data, which core's tests use. | macOS arm64, unsigned, same `node_modules` | trunk | this branch | |---|---|---| | `.app` on disk | 920 MB | **571 MB** | | zipped | 320 MB | **218 MB** | | `app.asar` | 205 MB | 108 MB | | `app.asar.unpacked` | 436 MB | 228 MB | | Electron Framework | 277 MB | 234 MB | ## How to test this Platforms: macOS and Windows, both needed, because the PHP runtime is chosen when the server starts and no CI job starts the real Playground server (see the Electron pin note in AGENTS.md). Use the Buildkite artifact for the current head commit. **Starting state:** the app from this branch's Buildkite build, with a site that has finished setup and whose server is stopped. 1. Open the site and click **Start development server**. The server comes up, and the site's front page and `/wp-admin/` both load in the browser. 2. Open the app's log for that site. It has no `Cannot find module` error, and no path containing `asyncify`. 3. In the settings, change the PHP version to 7.4, then start the server again. The site loads, and the log names PHP 7.4. 4. Use the app as usual: the site list, the terminal (xterm), the changed files, a dialog. Everything draws as before. The renderer no longer reaches `node_modules` for any of it. 5. On macOS, compare the size of the app with a trunk build in Finder (Get Info): about 570 MB against about 920 MB. **What must not have happened:** - The dev server failing to start, or starting on a PHP version other than the one chosen. - A blank or unstyled window, which would mean the renderer still needed a package that is no longer shipped. - Native form strings, such as a validation bubble, in a different language from before for cs, hu, nl, pl or English. ## Risks and limitations - The asyncify cut depends on Electron keeping JSPI. That is what `electron-wasm-jspi` guards. - On macOS, electron-builder also removes the grammatical-gender overlays (`cs_FEMININE.lproj` and similar) for the kept languages; each holds an 18-byte `locale.pak`. Chromium should fall back to the base locale, but I have not checked a macOS user with a grammatical gender set. - `electron-languages` copies electron-builder's matching rule, because it is not exported. An electron-builder release that changes that rule would not be caught. - Chromium's regional folding rules in `scripts/chromium-locales.cjs` follow `CheckAndResolveLocale` in Chromium's `l10n_util.cc`, but no Chromium source is vendored here to check them against. Only `en-ca` → `en-GB` affects today's list, and `en-GB` is kept for `en-gb` anyway. - `npm run i18n:download` now needs an installed Electron, which it downloads on first use. It reads Electron's locales before changing any catalog, so a failed download leaves everything as it was. - The packaged smoke suite passed locally only with `--user-data-dir` added to its launch, because a dev copy of the app held the single-instance lock. Trunk's build failed the same way without it. CI's run on this PR is the unmodified one. - Review: one completed fresh-context review, 0 findings; details below. ## Related - Fixes #703: the `asyncify/` folder of every PHP build is left out, which is the exclusion the issue proposes, and `electron-wasm-jspi` guards the JSPI it depends on. - Fixes #704: `@php-wasm/node-5-2`, the only installed build whose version `SupportedPHPVersions` does not report, is left out. `php-builds` fails when a Playground update changes which builds those are, and names the exclusion to add or remove. - Fixes #705: `build.electronLanguages` keeps only English and the Chromium locales of the app's catalogs, and `npm run i18n:download` keeps it in step. - Follow-up to #23, which reported the renderer-library half. That PR belongs to its author and is left as it is. --- <details> <summary>Design decisions and alternatives considered</summary> - **Exclusions in `build.files`, not a `postinstall` prune.** `node_modules` stays complete for development, the tests and the journeys. Only what electron-builder copies changes. - **`devDependencies` rather than more `!node_modules/...` lines.** The exclusion list from #563 had to grow every time a `@wordpress` package gained a dependency. Moving the cause leaves nothing to maintain, and lets 22 lines go. - **A hand-written `electronLanguages` list with a test, rather than one generated at build time.** A generated list would need a JS build config or a hook; a static list plus a test that names the missing entry is simpler, and changes only when a catalog is added. - **Chromium locales for the app's catalogs only.** Keeping a broader set would leave Chromium's strings in, say, Italian around an English app, which is no better than English. </details> <details> <summary>Review outcome (required — see AGENTS.md)</summary> 0 [fix here] · 0 [follow-up]. One style note was applied: the `electron-languages` header claimed Chromium's strings follow the app's language, but they follow the operating system's. - **Review:** completed. Reviewer: a separate Claude agent context, given only the diff and `.github/instructions/code-review.instructions.md`. Reviewed head `a7be033` against base `2dda92c` (`origin/trunk`). Evidence: `npm run lint` passed; `npm test` passed with 2202 tests, 2200 pass, 0 fail, 2 skipped; `npm run test:electron` passed with 2202 tests, 2201 pass, 0 fail, 1 skipped. The five dimensions found nothing. Specifically checked: no main-process, preload or runner import of a moved package; no production dependency still reaching a formerly excluded package; asyncify reached only when JSPI is absent, including for intl and xdebug; PHP 5.2 unreachable from the settings; electronLanguages against electron-builder's matching rule and the app's locale resolution. - **Since review:** `a7be033 → 7ac9e25` checked. The only change is the comment wording in `tests/unit/electron-languages.test.cjs`, and that test still passes. - **Since review:** `7ac9e25 → 8e1d005`, a CI fix, re-checked by the author against the same standard: 0 findings. CI's unit job failed because Electron 43's npm package downloads its binary on the first `require('electron')`, and three test files now asked for it at the same moment. I reproduced that locally by removing `node_modules/electron/dist`: two downloads ran and two tests failed. A `pretest` script now asks once before `node --test` starts, and the workflow comment that said `npm ci` fetches Electron is corrected. Run from a missing binary, `npm test` downloads once and passes 2200 tests with 0 failures, and `npm run test:electron` and `npm run lint` pass too. - **Review of `8e1d005 → dde0f94`** (the `i18n:download` change): completed by a separate Claude agent context against the same standard, in the context of `origin/trunk...dde0f94`. Result: 1 [fix here] · 0 [follow-up], fixed in `26e9250`. The finding: Electron's locale names were read after the catalogs had been replaced, so a failed Electron download would leave the run half applied. They are now read before anything is written. One style note was applied as well, a test title that claimed more than it asserted. The reviewer also ran about 130 slugs through the mapping without a crash, and checked that rewriting `package.json` reproduces the file byte for byte. Lint passes, and `npm test` and `npm run test:electron` each pass 2212 tests with 0 failures. - **Since that review:** `dde0f94 → 26e9250`. Only that fix and the renamed test changed; the suites above ran on `26e9250`. - **Since that review:** `26e9250 → 55ab855` adds only `tests/unit/php-builds.test.cjs`, for #704. I checked it against the standard myself: 0 findings. Broken both ways in turn (5.2 kept, 8.3 excluded), it fails each time, and it passes as committed. `npm test` and `npm run test:electron` each pass 2214 tests with 0 failures. - **CodeRabbit:** not requested yet. </details> <details> <summary>Implementation notes</summary> - Sizes come from `electron-builder --dir` with `-c.mac.identity=null -c.mac.notarize=false`, run twice from the same `node_modules` with trunk's and this branch's `package.json` and lockfile, then zipped with `ditto -c -k`. Signed artifacts will differ slightly. - Locally, from the trimmed package, `@php-wasm/node` booted PHP 7.4.33, 8.3.33 and 8.5.10 with `intl` loaded, run on the packaged binary with `ELECTRON_RUN_AS_NODE=1`. - `npm run test:e2e:packaged` passed all 15 tests on the trimmed build, including the first window painting, the preload bridge, and the `build.files` allow-list checks. - In the lockfile, the moved packages and their trees change from `devOptional` to `dev`. No versions change. - `pretest` runs `node -e "require('electron')"`. The electron package downloads its binary on the first `require`, so this fetches it once before `node --test` runs its files in parallel, where concurrent downloads raced. `npm run test:electron` already did this in its runner, and a single file run with `node --test <file>` has nothing to race with. - The asyncify choice is made in `@php-wasm/node/index.cjs` (`loadNodeRuntime`) and in each `@php-wasm/node-X-Y/index.cjs` (`getPHPLoaderModule` and the extension paths). </details> <details> <summary>Screenshots or recording</summary> Nothing on screen changes. </details> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The redesign in #542 is built on
@wordpress/uiand@wordpress/theme, and both are developed against the current@wordpress/components. The app is on 28, thirteen majors behind, so nothing from the design system can be added until the renderer stands on 41. This is the first step of #542 and changes no behaviour.What changes
@wordpress/componentsmoves from^28.2.0to^41.0.0and@wordpress/iconsfrom^10.7.0to^17.0.0. React stays on 18.3.1, which both packages support.editicon was removed from@wordpress/icons;pencilis the same glyph under its current name.build.filesexcludes the thirteen packages the update brought into the packaged app.@wordpress/components41 depends on@wordpress/uiand@wordpress/theme, and@wordpress/themenames esbuild as an optional peer, so npm stopped marking esbuild as dev-only and electron-builder started shipping its binary. None of the thirteen is loaded at run time: the renderer is the esbuild bundle, and nothing undersrc/requires them.Deliberately not in this PR: adding
@wordpress/uior@wordpress/themeas dependencies of the app, any use of design tokens, and any layout change. Those are the next steps of #542.How to test this
Platforms: any. Nothing here touches paths, spawning or signing. Use the Buildkite build for the current head of this branch.
The journeys carry the behavior:
npm run test:e2efrom the repository root drives every flow the renderer has through the updated components, andnpm run test:e2e:packaged, afterCSC_IDENTITY_AUTO_DISCOVERY=false npm run pack:dir, proves the packaged app still boots without the excluded packages. What they cannot see is how the app looks, so that is what a person should check.Starting state: the app open with at least one site that has finished setup.
What must not have happened:
Risks and limitations
trunkby mistake and removed again.trunkis back at 0dc54da; anyone who fetched in between has b6a6151 on their localtrunk.Related
Part of #542.
Fixes #548.
Design decisions and alternatives considered
Excluding in
build.filesrather than moving the renderer's dependencies todevDependencies. Moving them would stop the whole renderer-only tree from shipping, not just what this update added, but that is a change to how the app is packaged and #23 is already about it. This PR only undoes the growth it would otherwise cause.One jump from 28 to 41 rather than a major at a time. The renderer uses seventeen components, all of which still exist with the same props. The only break was the removed icon alias, which fails the build rather than the app.
Review outcome (required — see AGENTS.md)
2 [fix here] · 1 [follow-up] — both [fix here] fixed.
@wordpress/themenames esbuild as an optional peer and electron-builder collects optional packages.Style notes, not applied: with
white-space: nowrapthe sidebar title can paint outside the sidebar during the 200ms expand animation; theesbuild@0.23.1entry inallowScriptshas been stale since #538.b6a6151 → 4b2d52echecked. The difference is the thirteen exclusion lines inbuild.filesthat fix the two findings. It was not reviewed again by a fresh context; it was verified by packaging and running the packaged smoke test.Checks on 4b2d52e, macOS, local:
npm run lintnpm testnpm run test:electronnpm run test:e2enpm run test:e2e:packagedLint, the unit tests and the journeys ran on b6a6151; the second commit changes
build.filesonly, which none of the three reads.Implementation notes
app.asaron macOS arm64, unsigned,npm run pack:dir:The size on
trunkwas not measured.Packages excluded:
esbuild,@esbuild/*,@base-ui/*,@date-fns/*,@daypicker/*,react-day-picker,reselect,tabbable,colorjs.io,@wordpress/base-styles,@wordpress/kebab-case,@wordpress/style-runtime,@wordpress/ui. The list is the difference between the two lockfiles in what is not marked dev-only.@wordpress/components41 injects part of its CSS at run time through@wordpress/style-runtime. The renderer's content security policy already allows it (style-src 'self' 'unsafe-inline').Screenshots or recording
No images attached. The comparison was made between the committed docs screenshots and the same twelve shots captured on this branch with
npm run shots. What differs:🤖 Generated with Claude Code