build(ui): migrate to React 19 and Primer React 38 - #3383
Conversation
Replace removed Box and sx APIs with native styles and CSS Modules, load Primer CSS tokens, use the CSS-based theme provider and Banner, and scope custom-element JSX types to the React runtime. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Native numeric gaps incorrectly collapse Primer spacing, and reviewer-label backgrounds use an invalid CSS color token.
Review effort: Balanced
Findings: 5
Open (5)
What changed in this PR
Migrates all four MCP Apps views to React 19 and Primer React 38 without retaining styled-components compatibility.
Changes:
- Upgrades React, Primer, types, and lockfile dependencies.
- Replaces
Box/sxstyling with native styles and CSS Modules. - Adopts CSS themes and accessible critical banners.
| File | Description |
|---|---|
CONTRIBUTING.md |
Documents UI development and visual-review workflow. |
ui/package.json |
Upgrades React and Primer dependencies. |
ui/package-lock.json |
Locks the upgraded dependency graph. |
ui/src/styles.module.css |
Adds Markdown and truncation styles. |
ui/src/components/AppProvider.tsx |
Loads CSS themes and the new provider. |
ui/src/components/FeedbackFooter.tsx |
Replaces Box styling. |
ui/src/components/MarkdownEditor.tsx |
Migrates editor styling and JSX types. |
ui/src/apps/get-me/App.tsx |
Migrates profile-view styling. |
ui/src/apps/issue-write/App.tsx |
Migrates issue form and banners. |
ui/src/apps/pr-write/App.tsx |
Migrates PR creation UI. |
ui/src/apps/pr-edit/App.tsx |
Migrates PR editing UI. |
Files not reviewed (1)
- ui/package-lock.json: Generated file
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Replace leftover canvas.inset theme paths with the CSS custom property in PR creation and editing. Keep the reviewed native gaps unchanged. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Review follow-up: fixed the valid reviewer-label background issue mentioned in the review overview in ad936a1. Both PR forms now use The five gap threads have been replied to and resolved: their premise that bare Validation passed: |
Preserve main's MCP Apps SDK v2, TypeScript 7 and Node 26 updates alongside React 19 and Primer 38. Regenerate the lockfile with npm on Node 26. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Summary
Migrate the four MCP Apps views to React/React DOM 19.3.0, their 19.3.0 types, and Primer React 38.40.1. Replace removed styling APIs rather than adding the temporary styled-components compatibility package.
Why
Follow-up to #3370, which deferred these major upgrades for separate visual review. Based on latest main at cd50233; no issue closed.
What changed
Boxandsx/styled-system call site with native HTML/styles and CSS Modules for Markdown and nested selectors. Preserve layout scales, raw directgapvalues, truncation, custom-label colors and Markdown interactions.ThemeProviderfrom@primer/react/nextinstead of the deprecated JavaScript theme provider.Flashwith accessible criticalBannercomponents; augmentreact/jsx-runtimefor the Markdown custom elements. ExistingcreateRoot, refs and function defaults already meet React 19 requirements; no propTypes/legacy React DOM APIs were present.@modelcontextprotocol/ext-apps(1.7.5), TypeScript (5.9.3),@types/node(25.9.9), or their lock entries.Visual review
Captured baseline and upgraded builds in Chrome with a local JSON-RPC MCP Apps host fixture, using the actual built single-file HTML. Compared all four views in light/dark themes at 720px and 360px, plus Markdown previews, metadata menus, submitted success/error states and narrow custom issue fields. No new horizontal overflow or browser errors/warnings in the exercised flows.
Expected differences: Primer 38's token colors/borders and label typography differ slightly, especially in dark mode. Error messages now use a critical Banner with an icon and accessible region instead of deprecated Flash. Layout, form data, editor behavior and submission payloads remain unchanged.
Each comparison has before on the left, after on the right; rows are labeled by view. Screenshot data is synthetic and all tool calls are mocked.
All four views — light, 720px
All four views — dark, 720px
All four views — light, 360px
All four views — dark, 360px
Markdown previews — all three form views, light and dark
Error presentation — Flash to Banner
Submitted success states — all three form views
Metadata menus and narrow custom issue fields
Remaining risks
Draft intentionally pending human visual sign-off. Browser coverage used mocked tool responses in Chrome, not live authenticated VS Code/other MCP hosts or Firefox/Safari; host-specific rendering/focus should be checked before marking ready. The pre-existing Vite warning about a future native config loader and
__dirnameremains; Vite is not changed here. The UI package has no existingnpm testscript.Upgrade references reviewed: React 19 upgrade guide, Primer 37/38 changelog.
MCP impact
Prompts tested (tool changes only)
Security / limits
npm auditreports zero vulnerabilities.Tool renaming
deprecated_tool_aliases.goNote: if you're renaming tools, you must add the tool aliases. For more information on how to do so, please refer to the official docs.
Lint & tests
./script/lint—GOTOOLCHAIN=go1.26.8 script/lintpassed with 0 issues (installed Go 1.27 is too new for the pinned linter)../script/test—GOTOOLCHAIN=go1.26.8 script/testpassed, including the full Go race suite with the upgraded UI built.Additional evidence:
cd ui && npm ci && npm run typecheck && npm run build && npm audit— passed; all four self-contained HTML resources emitted, zero vulnerabilities.cd ui && npm ls --all— passed; no invalid peer dependencies.GOTOOLCHAIN=go1.26.8 go test ./pkg/github -run 'TestRegisterUIResources_ReadableViaClient|TestNewMCPServer_RegistersUIResources' -v— passed without skips; all four upgraded UI resources are embedded and readable through the Go MCP server.capture.mjs before/after— passed: 16 view/theme/width combinations and 12 preview screenshots per build.interactions.mjs before/after— passed: all three forms in both themes, exact bold-toolbar output, list continuation/exit, preview, metadata selections, submitted title/body/reviewer/label payloads, success/error states and narrow custom fields. Upgraded inactive-tab hover and Banner region assertions also passed.git diff --check— passed.Docs