feat(split): responsive + percentage snap points, snapFrom, onSnap callback#43
Merged
feat(split): responsive + percentage snap points, snapFrom, onSnap callback#43
Conversation
…llback Extends the snap points feature introduced in #37 with: - Percentage snap points (e.g. `'50%'`), resolved against the combined size of the two adjacent panes. - Responsive snap sets via Mantine breakpoint maps (e.g. `{ base: [200], md: [300, 500] }`). Closes #39. - `snapFrom?: 'before' | 'after'` prop on `Split` and `Split.Resizer` to interpret each snap point as the target size of the pane after the resizer instead of the pane before. Closes #40. - `onSnap?: (point: number | null) => void` callback on `Split.Resizer`, fired once on snap enter (with the resolved pixel value in the `snapFrom` reference) and once on exit (with `null`). Not fired on every pointer tick — state-based by design. Closes #41. - `data-snapping` attribute on the resizer root while inside a snap zone, for CSS-driven visual feedback. - Stricter `normalizeSnapPoints`: rejects negative values and malformed percentage strings; trims whitespace from valid percentage strings. Also extends `useResponsiveValue` to treat arrays as plain values so that `ResponsiveValue<T[]>` works correctly for array props.
Contributor
There was a problem hiding this comment.
Pull request overview
Extends Split/Resizer snap functionality to support percentage and responsive snap point sets, add snapFrom to snap relative to the after pane, and introduce an onSnap callback + data-snapping attribute for UI feedback.
Changes:
- Expand
snapPointsto acceptnumber | string(percentages) and responsive breakpoint maps; addsnapFromsupport. - Add
onSnap(point | null)eventing anddata-snappingstate while in a snap zone. - Update tests and docs with new behaviors and an “advanced snapping” demo.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| package/src/hooks/use-responsive-value.ts | Treat arrays as scalar values so responsive resolution doesn’t mis-handle snapPoints arrays. |
| package/src/Split.tsx | Plumbs snapFrom through Split → context so resizers can inherit it. |
| package/src/Split.test.tsx | Adds integration tests for percentage snapping, snapFrom="after", onSnap, and data-snapping. |
| package/src/Resizer/snap.ts | Adds snap point parsing/validation, percentage resolution, snapFrom, and reporting of snappedPoint. |
| package/src/Resizer/snap.test.ts | Adds/updates helper tests for new snap point types and snappedPoint reporting. |
| package/src/Resizer/SplitResizer.tsx | Resolves responsive snap sets, tracks snapping state, emits onSnap, and exposes data-snapping. |
| docs/docs.mdx | Documents percentage/responsive snap sets, snapFrom, onSnap, and data-snapping; adds advanced demo section. |
| docs/demos/index.ts | Exports the new snapAdvanced demo. |
| docs/demos/Split.demo.snapAdvanced.tsx | Adds a new demo showcasing percentages, snapFrom="after", responsive sets, and onSnap. |
Introduces a 4th docs tab (Upgrade guide) for documenting breaking changes
and step-by-step migration instructions per major version, keeping them
out of the main Documentation flow.
- DocsTabs: new optional `migrations` prop. When truthy, renders a tab
next to Documentation / Props / Styles API using IconArrowBarUp.
When omitted the tab is not rendered — default behavior for repos that
do not need it.
- migrations.mdx: collects v3 → v2 upgrade instructions previously
occupying the top ~160 lines of docs.mdx. Content is the same,
reorganized under a ## Upgrade guide title and reverse-chronological
## v3 / ## v2 sections so the TOC laterale acts as navigation.
- docs.mdx: replaces the in-page migration sections with a single
callout linking to /?t=migrations.
- DocsTabs.module.css:
- Add padding-top to .main so docs/migrations panels match the
vertical spacing of data-secondary panels (Props / Styles API).
- Neutralize margin-top of the first MdxTitle in .main to avoid
double spacing above the first heading.
- For the migrations panel only, drop the parent max-width and apply
flex: 1 / min-width: 0 on .main so the text-only content fills the
available width consistently with Documentation.
- pages/index.tsx: imports migrations.mdx and passes it to DocsTabs.
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.
Summary
Builds on top of #37 (merged) with the four enhancements we agreed on:
snapPointsnow acceptsArray<number | string>andResponsiveValue<...>snapFrom?: 'before' | 'after'(default'before')onSnapcallbackonSnap?: (point: number | null) => voidonSplit.Resizerdata-snappingattribute on the resizer root while in a snap zonePlus:
normalizeSnapPointsnow rejects negative values and malformed percentage strings, and trims whitespace from valid ones.useResponsiveValuetreats arrays as plain values (previously it would have tried to match an array as a breakpoint map).snapAdvanced).onSnapcallback semanticssnapFromreference — so forsnapFrom="after"you get back the target size of the right/bottom pane, matching what the user passed intosnapPoints).null.API shape decisions
onSnaplives only onSplit.Resizer(not cascaded via context). Rationale: with multiple resizers, a single callback onSplitwould receive events from all of them without a way to distinguish. Keeps v1 simple. A cascaded-with-meta variant can come later.snapFromis a single prop (not per-point). User preference: keep the simple case simple; the mixed case is rare enough to defer.Test plan
yarn test— 27/27 jest tests (17 snap helpers + 10 Split integration), 0 oxlint warnings, typecheck + format clean.yarn clean && yarn build && yarn docgen && yarn docs:build— all OK.onSnapreactivity,data-snappingattribute).Follow-up
After merge, release as minor (4.0.7 → 4.1.0). Changelog will credit @woutervanerp for the original snap points feature (already merged via #37) and cover these enhancements.