fix(components,app-shell): the last two direction props follow v4's rename to orientation - #3025
Merged
Merged
Conversation
… rename to `orientation` react-resizable-panels v4 renamed `PanelGroup`'s `direction` prop to `orientation`. Two call sites were still passing the v3 name, so v4 ignored it and React forwarded the unknown prop to the DOM as a stray `direction="horizontal"` attribute on the group div. Both groups are horizontal-only and `horizontal` is v4's default, so nothing rendered wrong — this is dead-prop cleanup, the tail of the migration whose visible half was #3024. Each site also carried `const PanelGroup = ResizablePanelGroup as React.FC<any>`, and those casts are why the dead prop survived the v4 bump: they erased the props to `any`, so `direction` type-checked against nothing. Both comments blamed the toolchain — vite-plugin-dts "not resolving the direction prop type correctly", and a prop that "does not always narrow cleanly in our TS config" — but neither was a narrowing problem. `GroupProps` simply has no `direction` key in v4. Dropping the casts makes the rename self-enforcing: restoring `direction` on the un-cast `ResizablePanelGroup` now fails with TS2322 rather than silently reaching the DOM. ResourceEditPage's `ResizablePanel` props are unaffected — `panelRef`, `collapsible`, `collapsedSize` and `onResize` are all valid v4 `PanelProps` and were never covered by the cast (it only ever wrapped the group), so no narrowly-typed workaround is needed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This was referenced Jul 30, 2026
os-zhuang
added a commit
that referenced
this pull request
Jul 30, 2026
…3025's dead prop, and pin the schema.direction boundary (#3036) Two follow-ups to #3025, both about stopping that bug from recurring. **The ratchet.** #3025 removed two `const PanelGroup = ResizablePanelGroup as React.FC<any>` casts. Those casts were not incidental to the bug — they caused it. Erasing a component's props to `any` meant that when react-resizable-panels v4 renamed `direction` to `orientation`, the stale prop type-checked against nothing and survived a whole major version as a dead prop React forwarded to the DOM. Deleting the casts is what turned it back into a hard TS2322. What makes this worth a ratchet rather than review vigilance is how both casts were justified: one blamed vite-plugin-dts for "not resolving the direction prop type correctly", the other a prop that "does not always narrow cleanly in our TS config". Neither was true — v4's `GroupProps` simply has no `direction` key. The cast reads as a workaround for a toolchain quirk while actually disabling the check that catches a breaking upstream rename, so it is the kind of thing that gets re-added in good faith. Repo-wide over `packages/<pkg>/src` and `apps/<app>/src`, following the existing `*.ratchet.test.ts` shape (#2269, ADR-0054) so it runs in the gating `pnpm test` job. Covers `FC` / `FunctionComponent` / `ComponentType` parameterised with `any`, qualified or not. Current count is zero, which is why now is the moment to set the gate. Three tests, because a ratchet has two silent failure modes of its own: a scan path that finds nothing, and a regex that stops matching. Both are pinned — the second against the exact casts #3025 removed, plus the legitimate neighbours it must not fire on (`as Record<string, any>`, `as ComponentProps<typeof Button>`, `const C: React.FC<Props>`). **The boundary comment.** `renderers/complex/resizable.tsx` maps `schema.direction` onto the library's `orientation`. That looks exactly like a site #3025 missed. It is not: `direction` is ObjectUI's own public authoring vocabulary and appears in stored view metadata, so renaming it to match the library would break every saved `resizable` schema. Said so in place, since the next person to grep for `direction` will land there. Verified the ratchet actually bites: reintroducing the exact cast into `custom/navigation-overlay.tsx` fails it with the file and line, and the four sibling ratchets plus the 15 resizable tests stay green. Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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.
Finishes the
react-resizable-panelsv3→v4 prop migration whose visible half landed in #3024.The dead prop
v4 renamed
PanelGroup'sdirectionprop toorientation. Two call sites were still passing the v3 name, so v4 ignored it and React forwarded the unknown prop straight to the DOM as a straydirection="horizontal"attribute on the group div:Both groups are horizontal-only and
horizontalis v4's default, so nothing rendered wrong. No visual change — this is dead-prop cleanup.Why it survived the v4 bump
Each site also carried a cast:
That cast is the reason the rename went unnoticed: it erased the props to
any, sodirectiontype-checked against nothing. Both comments blamed the toolchain — vite-plugin-dts "not resolving the direction prop type correctly", and a prop that "does not always narrow cleanly in our TS config" — but neither was a narrowing problem.GroupPropsin v4.12.2 simply has nodirectionkey; it hasorientation?: "horizontal" | "vertical".Casts removed,
ResizablePanelGroupused directly. The rename is now self-enforcing — reintroducingdirectionon the un-cast component fails:ResizablePanelprops: all valid v4, no workaround neededResourceEditPagealso passespanelRef,collapsible,collapsedSizeandonResize. All four are valid v4PanelPropsand all four type-check with no cast — they were never covered by it in the first place, since the cast only ever wrapped the group, not the panel.ResizablePanelis a bare re-export of the library'sPanel, so those props were already being checked strictly onmain. No narrowly-typed workaround is required.Verified against
react-resizable-panels@4.12.2's ownPanelProps:collapsedSize?: number | string,collapsible?: boolean,onResize?: (panelSize: PanelSize, id, prevPanelSize) => void,panelRef?: Ref<PanelImperativeHandle | null>.Verification
pnpm --filter @object-ui/components type-check— cleanpnpm --filter @object-ui/app-shell type-check— clean (0 errors)directionproduces the TS2322 above, then revertedresizable-orientation+form-field-panestests — 15 passedObjectView+FlowObjectListField.committests — 35 passedNo changeset — not a feature.
🤖 Generated with Claude Code