MUI 6 → 9 - #28
Merged
Merged
Conversation
Electron 32 is out of support (Electron keeps the latest three majors), so the 16 advisories that landed against it in August will never be patched there. 43.3.0 is current. Requires pinning node-abi: 4.26 does not know electron 43, so electron-builder's install-app-deps could not resolve the ABI and refused to rebuild the serialport bindings. That was the only breakage across eleven majors — no source change was needed. The API surface this app uses (app, BrowserWindow, ipcMain/ipcRenderer, contextBridge, shell.openExternal, setWindowOpenHandler) is unchanged, and webPreferences already used the sandbox/contextIsolation defaults Electron has been moving toward. Verified on macOS x64: typecheck, lint, 450 unit tests, all 604 e2e tests (01-main, 02-standalone, 03-presentation, 99-hardware against real devices), electron-builder packaging, and launching the packaged app. The serialport prebuild is a universal binary, so arm64 uses the same binding. Claude-Session: https://claude.ai/code/session_01LJ74fxYgZhmViUJdVxG6mb
@mui/material has no v8, so the breaking lines are 6->7 and 7->9. Both x-packages peer on ^5 || ^6 || ^7, so they move up alongside material 7. Four code changes, all forced by documented breaking changes: - v7 stops resolving deep imports more than one level in. Ten of them across RegisterGrid, BitMapRow and interpolation now come from the package root. - x-data-grid v8 no longer renders the toolbar slot implicitly; showToolbar is required. Without it the entire RegisterGridToolbar silently disappears -- load, save, clear and the whole options menu. Nothing catches this: no type error, no runtime error, no build warning. Only e2e found it. - x-data-grid v8 types its slots against a design-system-agnostic interface so the grid can run without Material UI, which means baseIconButton takes style/className but not sx. The interpolation action icon uses style. - useGridApiRef now returns RefObject<GridApi | null>, so setFilterModel is called through optional chaining. Verified: typecheck, lint, 450 unit tests, 572 e2e (01-main, 02-standalone, 03-presentation). Renderer bundle 3337.80 kB -> 3570.09 kB (+7%). Claude-Session: https://claude.ai/code/session_01LJ74fxYgZhmViUJdVxG6mb
Six type errors, each a documented v9 breaking change: - CheckCircleOutline was renamed to CheckCircleOutlined. - Typography no longer takes system props; fontSize/fontWeight move into sx. - AutocompleteRenderInputParams gathers everything under slotProps, so InputProps -> slotProps.input and inputProps -> slotProps.htmlInput. The spread has to merge into rest.slotProps rather than replace it, or the label and html input props are dropped. - The date-time picker's textField slot is a PickersTextField now, not a Material TextField, so its html input is reached through its own nested slotProps. - v9 slot props reject data-* keys unless the consumer opts in by augmenting DataAttributesOverrides (new src/renderer/src/mui.d.ts). The e2e suite depends on data-testid reaching slotted elements. And one test change: v9 split composite class names, so MuiAlert-standardWarning is now MuiAlert-standard plus MuiAlert-colorWarning. Verified: typecheck, lint, 450 unit tests, build. Renderer bundle 3570.00 kB, unchanged from v7. Claude-Session: https://claude.ai/code/session_01LJ74fxYgZhmViUJdVxG6mb
MuiButton-containedWarning is now MuiButton-contained plus MuiButton-colorWarning, which broke the RAW toggle test: its own guard used containedWarning to decide whether to reset the button first, so with raw mode left on by an earlier test the guard missed it, the click turned it off, and the assertion saw the off-state. setClientRawMode had two bugs that the rename forced into the open. It asserted not.toHaveClass in both branches, so the enabled path checked the opposite of what it set, and the else branch was never awaited. Neither showed up while containedWarning matched nothing. Claude-Session: https://claude.ai/code/session_01LJ74fxYgZhmViUJdVxG6mb
x-data-grid v8 moved the column headers inside the virtual scroller so it can virtualise columns. Both grids scoped their monospace font to .MuiDataGrid-virtualScrollerContent, which used to cover the data rows only, so every column header silently switched to monospace. Scoping to .MuiDataGrid-row restores the previous rendering. Found by diffing the presentation screenshots against main, not by a test: nothing asserts on fonts, and the suite takes 29 screenshots without comparing them. Claude-Session: https://claude.ai/code/session_01LJ74fxYgZhmViUJdVxG6mb
Three components were painting over the grid, and two of those paints did nothing at all. GridHeader renders the toolbar slot bare -- no wrapper element, no class -- so `.MuiDataGrid-toolbarContainer` only exists when you use MUI's own GridToolbar. All three grids styled that selector; none of them has that element. The rule was dead before v9 and stayed dead. The one paint that did land was RegisterGridToolbar's own background, set to palette.background.default. That matched while the grid base matched it too. v9 lightens the base in dark mode (color-mix of paper with white) and headerBg falls back to it, so the headers moved and the toolbar did not. Fixed through the palette instead: DataGrid.headerBg pins the header strip to the app background, which is what the toolbar sits on. Setting bg would have flattened the rows and footer as well, which is not wanted -- headerBg alone covers exactly the strip. ScanUnitIds still scoped its monospace font to virtualScrollerContent, which v8 turned into a selector that also catches the column headers. Now on .MuiDataGrid-row like the other two grids. Verified against the presentation screenshots: the header background is back to went from 7 to 10 with the largest diffs gone.
This was referenced Aug 27, 2026
Merged
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.
Stacked on #27, which is why the base is not
main. Two hops: 6 → 7 first, taking x-data-grid to 8 and x-date-pickers with it, then 7 → 9.Most of the diff is the lockfile. What changed in the app is small, and each piece is a reaction to how v9 renders rather than a choice:
mui.d.tsis new — the theme augmentation v9 expects.Lint, typecheck, the unit tests and the full e2e suite are green, in dev and packaged mode, on
ubuntu-22.04,ubuntu-22.04-arm,macos-26,macos-26-intelandwindows-2025.What this is waiting on
How it looks. A major version of a component library moves spacing, borders and colours in ways no assertion notices — and the list above is itself evidence of that, since every item is a rendering difference the suite did not report. It says this still works. It cannot say it still looks right.
Draft until that judgement is made, and behind #27 either way.