Skip to content

4.0.0

Choose a tag to compare

@gfazioli gfazioli released this 01 Apr 13:52
· 87 commits to master since this release

Caution

This is a major release with breaking changes. Mantine 9, React 19, and TypeScript 6 are now required. See the Migration Guide below.


Breaking Changes

1. Mantine 9 required

@mantine/core and @mantine/hooks have been upgraded from v8 to v9. Mantine 9 includes breaking changes in its own API — consult the Mantine 9 changelog for details.

The peer dependency range remains >=7.0.0, but v4.0.0 of this package is built and tested against Mantine 9.

2. React 19 required

React has been upgraded to 19.2.4. React 19 introduces native ref forwarding — components no longer use React.forwardRef. The peer dependency allows both ^18.x || ^19.x, but React 19 is recommended.

3. TypeScript 6 required

TypeScript has been upgraded from 5.9.x to 6.0.2. TypeScript 6 deprecates moduleResolution: "node" in favor of "bundler" and enforces stricter null checks on useRef and optional properties.

4. createOptionalContext replaced with createSafeContext

Mantine 9 removed createOptionalContext from @mantine/core. The internal SplitContext now uses createSafeContext, which throws a clear error ("Split component was not found in tree") if Split.Pane or Split.Resizer are used outside a <Split> parent1.

Note

If you previously rendered <Split.Resizer> standalone (e.g., in Storybook stories), it must now be wrapped in <Split> with at least two <Split.Pane> siblings.

5. Ref forwarding changes (internal)

All three factory components (Split, Split.Pane, Split.Resizer) no longer accept ref as a second argument in their factory callbacks. Split extracts ref from props and merges it with the internal ResizeObserver ref via useMergedRef. Split.Pane extracts ref for useImperativeHandle. Split.Resizer does not use an external ref.

Note

This change is transparent to consumers — ref props on <Split ref={myRef} /> and <Split.Pane ref={paneRef} /> continue to work as expected. No changes are needed in your application code.

6. Variant color resolver fields now optional

The SplitResizerVariantColorResolverResult interface fields color, hover, and knob are now optional (string | undefined instead of string). This prevents empty string values from being written into CSS variables when no color is configured, letting theme defaults take effect properly.

Bug Fixes

1. child.key falsy values preserved in auto-resizer mode

Changed child.key || fallback to child.key ?? fallback in the auto-resizer children cloning logic. Previously, valid falsy keys like 0 would be replaced, causing unstable React keys.

Improvements

1. Storybook upgraded to v10

Storybook has been upgraded from v8 to v10. Layout changed from centered to padded for proper split pane rendering. SplitResizer stories now wrap the resizer in a <Split> parent with two panes (required by createSafeContext).

2. Prettier replaced by oxfmt

The code formatter has been switched from Prettier to oxfmt, a Rust-based formatter.

Before After
yarn prettier:check yarn format:test
yarn prettier:write yarn format:write

3. Ref merge simplified with useMergedRef

Split.tsx replaced a manual ref merge callback (that handled function refs and object refs separately) with Mantine's useMergedRef hook for combining the external forwarded ref with the internal ResizeObserver ref.

4. TypeScript 6 strict null safety

Added null guards and optional chaining throughout SplitPane.tsx and SplitResizer.tsx to satisfy TypeScript 6's stricter null checks on useRef.current, optional method calls, and getBoundingClientRect() access.

Other Changes

  • CI workflow updated for the new toolchain
  • tsconfig.build.json updated with explicit rootDir and narrowed include for TypeScript 6 compatibility
  • docs/tsconfig.json updated to moduleResolution: "bundler" and target: "es2015"
  • Documentation site dependencies updated: Next.js 15.5.14, @mantine/code-highlight 9.0.0
  • Shell and Footer documentation components refreshed from the base template
  • containerRef in SplitResizer now explicitly typed as useRef<HTMLButtonElement>(null)
  • Story file type error fixed (handleResize width parameter)

Migration Guide (v3 → v4)

Step 1: Update dependencies

npm install @gfazioli/mantine-split-pane@4
npm install @mantine/core@9 @mantine/hooks@9 react@19 react-dom@19

Step 2: Follow the Mantine 9 migration guide

Consult the Mantine 9 migration guide for any breaking changes that affect your usage of Mantine components.

Step 3: Update TypeScript (if applicable)

npm install typescript@6

Update your tsconfig.json to use "moduleResolution": "bundler" instead of "node".

Step 4: Wrap standalone SplitResizer in stories/tests

If you render <Split.Resizer> without a <Split> parent, wrap it:

// Before
<SplitResizer variant="filled" />

// After
<Split h={200}>
  <Split.Pane>Pane 1</Split.Pane>
  <SplitResizer variant="filled" />
  <Split.Pane>Pane 2</Split.Pane>
</Split>

Step 5: No component API changes

The Split, Split.Pane, Split.Resizer, and Split.Dynamic components retain the same props and behavior. No changes to your JSX are required.


Summary

@gfazioli/mantine-split-pane v4.0.0 is a major infrastructure upgrade — Mantine 9, React 19, TypeScript 6, Storybook 10, and oxfmt replace the previous toolchain. The key migration-specific change is replacing createOptionalContext with createSafeContext, enforcing that sub-components are always used within a <Split> parent. All 1 test passes; the component API is unchanged.


What's Changed

    • ✨ feat: upgrade to Mantine 9, React 19, TypeScript 6, and Storybook 10 by @gfazioli in #36

Full Changelog: 3.0.0...4.0.0

  1. This matches Mantine 9's pattern for required parent-child relationships (Drawer, Tabs, etc.). Split.Pane and Split.Resizer cannot function without <Split> because they depend on container size tracking and cascaded resizer configuration. ↩