build(deps-dev): L3-0000 bump vite to 8 and merge React 19 upgrade - #907
dependabot[bot] wants to merge 16 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot could not run the full agentic suite for this review because it was automatically requested on a bot-authored pull request. Request a review from Copilot under Reviewers to retry with the full agentic suite. Improved support for bot-authored pull requests is coming soon.
Updates the Vite toolchain versions in package.json.
Changes:
- Bumped
@vitejs/plugin-reactfrom^5.1.4to^5.2.0 - Bumped
vitefrom^7.3.1to^8.1.5
| "@typescript-eslint/eslint-plugin": "^8.18.0", | ||
| "@typescript-eslint/parser": "^8.18.0", | ||
| "@vitejs/plugin-react": "^5.1.4", | ||
| "@vitejs/plugin-react": "^5.2.0", |
| "typescript": "^5.5.4", | ||
| "typescript-eslint": "^8.18.0", | ||
| "vite": "^7.3.1", | ||
| "vite": "^8.1.5", |
✅ Deploy Preview for phillips-seldon ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) and [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react). These dependencies needed to be updated together. Updates `vite` from 7.3.1 to 8.1.5 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v8.1.5/packages/vite) Updates `@vitejs/plugin-react` from 5.1.4 to 5.2.0 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/plugin-react@5.2.0/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@5.2.0/packages/plugin-react) --- updated-dependencies: - dependency-name: "@vitejs/plugin-react" dependency-version: 5.2.0 dependency-type: direct:development - dependency-name: vite dependency-version: 8.1.5 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com>
ed8e915 to
17719e8
Compare
Bumps the dev dependency on React from 18.3.1 to 19.2.8 while preserving the peer-dependency contract that already allowed both React 18 and React 19 consumers. Also brings along the React ecosystem packages whose peer types explicitly excluded React 19. Superseded by attempt #808 (react-dom bumped without react — inconsistent). ## Dependency changes Dev dependencies bumped: - react 18.3.1 → 19.2.8 - react-dom 18.2.0 → 19.2.8 - @types/react 18.3.3 → 19.2.17 - @types/react-dom 18.0.11 → 19.2.3 - @testing-library/react 16.0.0 → 16.3.2 (React 19 peer support) - usehooks-ts 3.1.0 → 3.1.1 (React 19 peer support) - @chromatic-com/storybook 5.0.1 → 5.2.1 (Storybook 10.6.x peer support) Added: - @testing-library/dom ^10.4.1 (peer requirement of @testing-library/react 16.x) peerDependencies unchanged — still declares `"react": "^18.3.1 || ^19.0.0"` and `"react-dom": "^18.2.0 || ^19.0.0"`, so consumers can stay on 18 or move to 19. ## Code changes for React 19 compat RefObject prop types widened from `RefObject<T>` to `RefObject<T | null>` (React 19 `useRef<T>(null)` now returns the narrower nullable type): - CarouselDot.tsx (`scrollableContainerRef`) - CountryPickerCountryList.tsx (`listRef`) - FavoritesCollectionTile.tsx (`imageRef`) - ComboBox.tsx (widened prop + cast for usehooks-ts `useOnClickOutside`) `useOnClickOutside` cast at call site (usehooks-ts still types as `RefObject<T>`) — Search.tsx, ComboBox.tsx. JSX namespace no longer global in React 19; switched to `React.JSX.Element` or added `import type { JSX }` — utils/index.tsx, DetailList.stories.tsx, ProgressWizard.stories.tsx. `React.Children` / `cloneElement` stricter — added explicit generics on `isValidElement<Props>()` and typed cloneElement calls: - DetailList.tsx, NavigationSubmenu.tsx, Toast.test.tsx, FilterMenu.tsx, ProgressWizard/utils.tsx. DatePicker.tsx — `useRef()` now requires an initial value; added `null`/`undefined`. Also removed `extends Record<string, unknown>` from DatePickerProps (was silently marking every prop `unknown`), typed forwardRef explicitly, made `locale` optional to match its `= 'en'` default. StatefulViewingsList.tsx — removed the same latent `extends Record<string, unknown>` bug; replaced with `extends Omit<ViewingsListProps, ...>` so the spread of forwarded props remains legal. Search.tsx — added `nodeRef={searchInputRef}` to `<CSSTransition>` so react-transition-group no longer calls the removed `ReactDOM.findDOMNode`. SeldonImage.tsx — switched the workaround `fetchpriority` (lowercase HTML attr) back to the proper camelCase `fetchPriority` which React 19 now handles natively; removed the accompanying `@ts-expect-error` and eslint-disable. Also guarded empty `src` with `src || undefined` to satisfy React 19's stricter empty-string warning. Button.test.tsx — React 19 hoists `<link>` elements to `<head>`, so the prefetch-link assertions now query `document.head`. ## Verification - npm run build → exit 0 (tsc + vite build) - npm run lint → exit 0 (tsc --noEmit, eslint, stylelint, markdownlint) - npx vitest run --project=unit → 1042 / 1042 passing Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Storybook 10.2.8's vite peer range (^5||^6||^7) rejected the vite@8 bump. Bumped @storybook/* and eslint-plugin-storybook to ^10.5.5 which widened the peer range to include vite@8. Pinned typescript, react, react-dom, @types/react, @types/react-dom, ics, vitest, and glob to match main's lockfile so a fresh install does not regress on latent typing/runtime issues in DatePicker, StatefulViewingsList, Search, and calendarLinks. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two behavior-preserving fixes flagged by code review:
1. SeldonImage — empty src no longer silently skips the error UI.
Previously `<img src="">` fired the browser onError event which
set loadingState to 'error' and showed the error icon. With
`src={src || undefined}` (to silence React 19's empty-src warning)
the error path never triggered. Now initialize loadingState to
'error' when !src, and short-circuit the async loadImage so it
doesn't fire a stray setState after unmount.
2. Search — CSSTransition classes now land on the wrapper div, not
the inner <input>. React-transition-group's findDOMNode used to
return Input's outermost DOM node (the wrapper <div>) so
`.seldon-input-enter` classes were applied there. Switching to
`nodeRef={searchInputRef}` shifted them to the input element
itself, a silent DOM-target change for any downstream consumer
styling those transition classes. Added a dedicated
searchInputWrapperRef and a wrapping div so nodeRef targets the
wrapper.
Verified: build passes, lint passes, 1042/1042 unit tests pass, no
unhandled rejections.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lti-eebdba2d21 # Conflicts: # package-lock.json # package.json
The prior wrapper-div fix around <CSSTransition> introduced an extra block that disrupted the flex chain, pushing the input to a new row. Removes the wrapper and lands the transition classes on the <input> directly, then updates the SCSS selector from `.seldon-input-enter-active input` (descendant) to `.seldon-input__input.seldon-input-enter-active` so the enter-active background/placeholder styling still applies. Also: - Drops stale explanatory comments across Search, SeldonImage, and the Button test helper that documented the React-18→19 delta rather than the code's current behavior. - Adds .claude/worktrees to eslint ignores so lint doesn't fail on files that belong to a locked git worktree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Prevents `.claude/worktrees/` from being accidentally added as a submodule entry when the pre-commit hook runs `git add .`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vite@8 double-wraps CJS default exports in the browser (l10n.default.en), while node/jsdom still returns the unwrapped shape (l10n.en). Add a runtime check so both interop patterns resolve to the locale table. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the eslint-config change so `npm run coverage` and the pre-push hook don't pick up test files in a locally-checked-out worktree. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…endabot/npm_and_yarn/multi-eebdba2d21
- vite@8's rolldown-based CSS pipeline no longer applies resolve.alias to sass @use/@import. Add an explicit sass importer in .storybook so ~scss/allPartials keeps resolving. - vite@8 minifies CSS with lightningcss, which rejects var('...') with quoted identifiers. Remove the stray quotes in _composedModal.scss. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Tip All tests passed and all changes approved!🟢 UI Tests: 476 tests unchanged |
|
🚀 Storybook preview is ready. • Preview: https://68b9f094608b90f3cfec5a06-asrqycqxky.chromatic.com/ |
🔴 Dependency Upgrade Risk Assessment:
|
| Package | From | To | Type |
|---|---|---|---|
vite |
7.3.1 | 8.1.5 | Major version |
@vitejs/plugin-react |
5.1.4 | 5.2.0 | Minor |
react / react-dom |
18.x | 19.x | Major version |
@types/react / @types/react-dom |
18.x | 19.x | Major |
storybook (full family) |
10.2.8 | 10.5.5 | Minor |
Why does this matter for the broader Phillips ecosystem?
Seldon is the internal Phillips UI component library used by phillips-public-remix (and potentially other Phillips apps). Every component, design token, and primitive exported from seldon is consumed downstream. A regression in seldon's build output or type signatures cascades immediately to all consuming applications.
How widespread is the usage?
Seldon exports are used pervasively throughout phillips-public-remix — every page component, most route-level components, and the majority of UI primitives (Button, Text, Grid, Loader, Toast, tabs, modals, etc.) are sourced from this library. Breaking the seldon build or introducing type incompatibilities would block the entire consumer app from building.
What changed and what workarounds were needed?
The PR body documents several non-trivial compatibility issues that required active fixes:
- vite 8 CSS pipeline (rolldown-based) — vite 8 replaced its CSS processing engine with rolldown. The new pipeline stopped applying
resolve.aliasto@use/@importSCSS directives, breaking~scss/allPartialsresolution. A customfindFileUrlimporter had to be added to.storybook/main.tsto restore this. - CSS custom property syntax — lightningcss (vite 8's default CSS minifier) rejects quoted
var()values (var('--foo')). Stray quotes in_composedModal.scsshad to be stripped. - flatpickr l10n import interop — vite 8's CJS interop changed how
flatpickr/dist/l10n/indexis resolved between node (jsdom) and browser bundles. A shim was needed inDatePicker.tsx. - React 19 type-level breaking changes —
Record<string, unknown>intersections removed, explicitforwardRefgenerics required,useRefinitial-value pattern updated. These are compile-time changes that affect any component using these patterns.
Why HIGH?
- Multiple simultaneous major-version upgrades — vite 8 + React 19 together multiply the risk surface; each has its own breaking changes and the combination creates emergent compatibility issues (as the workarounds show).
- Seldon is a shared infrastructure library — a regression in its build output affects all downstream consumers, not just this repo.
- Build pipeline change — vite 8's rolldown CSS engine processes SCSS differently. Any component using
@use/@importpatterns that weren't tested could produce broken CSS in production. - React 19 downstream impact —
phillips-public-remixcurrently uses React 18. When seldon ships React 19 types, consuming apps may see type errors until they also upgrade. - Workarounds indicate fragility — the number of fixes needed in this PR (3+ distinct compatibility shims) suggests the upgrade surface is broad and other edge cases may remain.
Suggested Regression Tests
Before merging, confirm the following:
Build & Lint
-
npm cisucceeds without--legacy-peer-deps -
npm run buildcompletes without errors (vite 8 production build) -
npm run build:storybookproduces a validstorybook-static/directory -
npm run lintpasses cleanly
Unit & Storybook Tests
- All unit tests pass:
npm test -- --run(target: 1042/1042) - All Storybook interaction tests pass:
npm run test-storybook(target: 238/238)
Key Component Smoke Tests (most likely affected by the workarounds)
- DatePicker — open the component in Storybook, confirm English weekday shorthand renders correctly (validates the flatpickr l10n interop fix for both dev and production builds)
- ComposedModal — open in Storybook, confirm the modal body height CSS custom property (
--max-modal-body-height) applies correctly (validates the lightningcssvar()fix) - Any component using
forwardRef— verify no TypeScript errors and correct runtime behavior
Chromatic Visual Regression
- Compare Chromatic snapshots against
main— visual diffs should be limited to intentional React 19 surface changes; flag any unexpected layout or style regressions
Downstream Consumer Validation
- After publishing a preview/canary build of seldon, install it in
phillips-public-remixand confirm:npm install,npm run typecheck, andnpm run buildall pass without requiring React 19 types in the consumer (or document that a consumer upgrade is also required) - Verify CSS-heavy components (anything using
~scss/allPartials) render correctly when consumed via the built package (not just in Storybook dev mode)
Generated by Claude Code
vite build exits 0 even when dist/ cannot actually be loaded by an ESM
consumer, so add `npm run smoke` (wired into CI) that loads dist/index.js
and dist/index.cjs the way consumers do and scans for unresolvable runtime
`__require(...)` calls and bundled peer deps.
Externalize @artsy/fresnel: Rolldown cannot hoist its `require('react')`
into a static ESM import when it bundles the package, so the output ships
a runtime `__require('react')` that throws for every ESM consumer.
Also refactor buildUtils tests to use `vi.hoisted` so `glob.sync` is
mockable per-test, and prevent jsdom "Not implemented: navigation" noise
by cancelling default anchor clicks in the shared test setup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Jira ticket
L3-0000 (dependabot bundled upgrade)
Screenshots
Figma link
n/a
Summary
Upgrade Vite (7.3.1 → 8.1.5) and
@vitejs/plugin-react(5.1.4 → 5.2.0) as dependabot proposed, plus everything else needed to make the tree install and CI pass:@storybook/react-vite's peer range acceptsvite@^8.chore/react-19-upgradeso@types/react,react, andreact-domland at v19 in the same PR.flatpickr's l10n export (l10n.default.enin the browser vsl10n.enin jsdom).findFileUrlimporter in.storybook/main.tsbecause vite@8's rolldown-based CSS pipeline stopped applyingresolve.aliasto@use/@import, which was breaking~scss/allPartials.var('--…')in_composedModal.scss— lightningcss (vite@8's default CSS minifier) rejects the quoted form.icsand add explicitglobso the fresh lockfile does not regress on latent code paths.Verified all vite-adjacent plugins (
vite-plugin-dts,vite-plugin-svgr,vite-tsconfig-paths,@vitejs/plugin-react,@storybook/{react-vite,builder-vite}) declare peer ranges that includevite@^8; no further plugin bumps required.Change List (describe the changes made to the files)
package.json,package-lock.json: bumpvite→ 8.1.5,@vitejs/plugin-react→ 5.2.0,@storybook/*+eslint-plugin-storybook+storybook-addon-pseudo-states→ ^10.5.5, add explicitglob, pinics, plus the React 19 dep upgrades fromchore/react-19-upgrade..storybook/main.ts: register a sassfindFileUrlimporter that maps~scss/*tosrc/scss/*.src/components/DatePicker/DatePicker.tsx: unwrap theflatpickr/dist/l10n/indexdefault import so both node and vite-bundled browser interop resolve to the locale table.src/components/ComposedModal/_composedModal.scss: remove quotes fromvar('--max-modal-body-height').chore/react-19-upgrade(removedRecord<string, unknown>intersections, explicitforwardRefgenerics, updateduseRefinitial-value pattern, etc.).Acceptance Test (how to verify the PR)
npm cisucceeds (no--legacy-peer-depsneeded).npm run buildsucceeds.npm test -- --run— 1042/1042 unit tests pass.npm run test-storybook— 238/238 storybook tests pass.npm run build:storybooksucceeds and producesstorybook-static/.npm run lintis clean.Regression Test
main— visual diffs should be limited to the intentional React 19 surface changes.~scssimporter still resolves and the CSS custom property still applies.Evidence of testing
npm ci && npm run build && npm test -- --run && npm run test-storybook && npm run build:storybook && npm run lintall pass on macOS with Node 22.var()fixes landed.Things to look for during review
feat(scope): ...if aminorrelease should be triggered.phillipsclass prefix are using the prefix variabledata-testidattribute.