Skip to content

chore(ui): unify monorepo on React 19#6584

Merged
otavio merged 2 commits into
masterfrom
chore/ui/react-19
Jun 30, 2026
Merged

chore(ui): unify monorepo on React 19#6584
otavio merged 2 commits into
masterfrom
chore/ui/react-19

Conversation

@luizhf42

Copy link
Copy Markdown
Member

What

Move every ui/ workspace onto a single React 19 major. react/react-dom are now hoisted once at the workspace root, the per-app pins are removed, and the console source is migrated to React 19's type and runtime changes.

Why

The monorepo pinned two React majors — apps/docs on ^19, apps/console and apps/website on ^18. Because npm workspaces hoist the most-shared version, React 18 landed at the root and docs nested its own React 19, so a root-hoisted React-18 component rendered by docs' React 19 react-dom/server crashed astro build ("Objects are not valid as a React child"), and the two @types/react copies disagreed (bigint in ReactNode), breaking tsc. This blocked bringing @heroicons/react into docs and was a latent footgun for any pre-compiled React dependency used across the boundary. This executes Option B from the issue (move everything forward) rather than downgrading docs.

Closes #6583

Changes

  • deps: hoist react/react-dom/@types/react/@types/react-dom ^19.1.0 to the root package.json; drop the redundant react/react-dom/@types pins from console, website, and docs so all apps resolve one major.
  • deps: bump @stripe/react-stripe-js ^2.8.0^3.1.1 — the only dependency without React 19 support. v3.1.x adds React 19 while still accepting @stripe/stripe-js@^4, so the existing @stripe/stripe-js pin is unchanged. Every other React-coupled dependency (@tanstack/react-query, zustand, react-router-dom, @tiptap/react, @heroicons/react, @fortawesome/react-fontawesome, @testing-library/react, @astrojs/react) already declares ^19 support.
  • console: applied types-react-codemod for the three breaking type categories — the removed global JSX namespace (JSX.ElementReact.JSX.Element), callback refs that may no longer return a value, and RefObject<T> widening to RefObject<T | null>.
  • console: changed inert from a string to a boolean attribute (inert={true}), which React 19 now requires — this also fixed three tests asserting closest("[inert]") and silences a runtime warning that existed before.
  • build: ignore the tsc -b-emitted openapi-ts.config.d.ts, a pre-existing .gitignore gap the build surfaced (the vite.config.d.ts sibling was already ignored).

Testing

Run inside the ui container: npm run build (all workspaces, includes tsc -b), npm run lint -w @shellhub/console (0 errors), and npm run test (console 2536, website 71, design-system 192, docs 15 — all pass). Manually smoke the billing card form (apps/console/src/components/billing/BillingPayment.tsx), the only consumer of the bumped Stripe package.

luizhf42 added 2 commits June 30, 2026 14:17
The ui/ workspaces pinned two React majors: docs on 19, console and
website on 18. npm hoisted React 18 to the root and nested 19 under
docs, so a root-hoisted React-18 component rendered by docs' React 19
crashed astro build, and the two @types/react copies disagreed and
broke tsc.

Hoist a single react/react-dom 19 at the root, drop the per-app pins,
and bump @stripe/react-stripe-js to ^3.1.1 (the only dependency without
React 19 support; keeps @stripe/stripe-js 4). Console code is migrated
via types-react-codemod plus the inert string-to-boolean change.

Fixes: #6583
tsc -b emits a declaration file for the composite openapi-ts.config.ts,
but .gitignore only covered the vite.config.d.ts sibling, leaving the
artifact tracked as untracked after every build.
@luizhf42 luizhf42 requested review from a team as code owners June 30, 2026 17:24
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown

Claude finished @luizhf42's task in 5m 42s —— View job


Code Review Complete

Reviewed 21 files across code quality, security, testing, language patterns, and architecture — no new issues found. The code looks good as-is.

Key verifications:

  • React 19 type migrations are complete — all RefObject<T> usages include | null, all JSX namespace references have explicit imports, callback refs are void-returning, and inert attributes use boolean values. No files were missed.
  • @stripe/react-stripe-js v2→v3 is API-compatible — the only consumer (BillingPayment.tsx) uses stable APIs (Elements, CardElement, useStripe, useElements), and the deprecated PaymentRequestButtonElement is not used.
  • @shellhub/design-system declares react: "^18 || ^19" as its peer dependency, so it accepts the hoisted React 19 without issue.
  • The hoisting strategy is correct — all three workspaces (console, docs, website) will resolve to the single root React 19 instance.
  • Cloud repo (cloud/) contains only Go code — zero cross-repo React impact.
  • Existing tests use value-agnostic attribute checks ([inert], toHaveAttribute("inert")) that work with both the old string and new boolean forms.

If you push additional changes and want a new review, tag @shellhub-io/admin and a team member can trigger it.


@otavio otavio merged commit 35ef69f into master Jun 30, 2026
15 checks passed
@otavio otavio deleted the chore/ui/react-19 branch June 30, 2026 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unify the React major version across ui/ workspaces (docs on 19, console/website on 18)

2 participants