react-resizable-panels-v3-to-v4

Use when upgrading react-resizable-panels from v3 to v4, fixing v4 type/runtime errors (PanelGroup not exported, direction prop invalid, layout broken), adapting to the new Group/Separator API and percentage string syntax, or updating CSS selectors for renamed data attributes. Triggers on "react-resizable-panels v4", "PanelGroup not found", "PanelResizeHandle not found", "panel layout broken after upgrade".

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-resizable-panels-v3-to-v4" with this command: npx skills add wenerme/ai/wenerme-ai-react-resizable-panels-v3-to-v4

react-resizable-panels v3 → v4 迁移指南

概述

react-resizable-panels v4 是一次重大版本升级。核心变化:组件重命名(ARIA 对齐)、尺寸单位系统重构(数字从百分比变为像素)、移除 order prop、移除 onCollapse/onExpand。本技能覆盖迁移的所有关键路径。

迁移步骤总览

Step 1: 安装

pnpm add react-resizable-panels@4
# 或
npm install react-resizable-panels@4

Step 2: 组件重命名

v3v4说明
PanelGroupGroup容器组件重命名
PanelResizeHandleSeparator分隔条重命名,对齐 ARIA separator role
PanelPanel不变
- import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
+ import { Panel, Group, Separator } from 'react-resizable-panels';

- <PanelGroup direction='horizontal'>
+ <Group orientation='horizontal'>
    <Panel />
-   <PanelResizeHandle />
+   <Separator />
    <Panel />
- </PanelGroup>
+ </Group>

Step 3: 类型重命名

v3 类型v4 类型说明
PanelResizeHandlePropsSeparatorProps随组件重命名
PanelOnCollapse已移除onResize 替代
PanelOnExpand已移除onResize 替代
ImperativePanelGroupHandleGroupImperativeHandle重命名
ImperativePanelHandlePanelImperativeHandle重命名
(新增) PanelSize{ asPercentage: number; inPixels: number }新类型
- import type { PanelResizeHandleProps } from 'react-resizable-panels';
+ import type { SeparatorProps } from 'react-resizable-panels';

- import type { PanelOnCollapse, PanelOnExpand } from 'react-resizable-panels';
+ // 已移除,改用 Panel 的 onResize 回调

Step 4: Props 变更

Group (原 PanelGroup)

v3 Propv4 Prop说明
directionorientation重命名,对齐 ARIA 标准
autoSaveId已移除useDefaultLayout hook 替代
ref={groupRef}groupRef={groupRef}ref 改为命名 prop
onLayoutonLayoutChange / onLayoutChanged重命名并拆分
- <PanelGroup direction='horizontal' autoSaveId='my-layout' ref={groupRef}>
+ <Group orientation='horizontal' groupRef={groupRef}>

Panel

v3 Propv4 Prop说明
order已移除条件渲染不再需要 order
onCollapse已移除onResize 替代
onExpand已移除onResize 替代
ref={panelRef}panelRef={panelRef}ref 改为命名 prop
- <Panel id='left' order={1} onCollapse={handleCollapse} onExpand={handleExpand}>
+ <Panel id='left' onResize={(nextSize, id, prevSize) => {
+   if (prevSize) {
+     const wasCollapsed = prevSize.asPercentage === 0;
+     const isCollapsed = nextSize.asPercentage === 0;
+     if (isCollapsed && !wasCollapsed) handleCollapse();
+     if (!isCollapsed && wasCollapsed) handleExpand();
+   }
+ }}>

Step 5: 尺寸单位转换(关键!)

v3: 所有 size 值为数字,隐式表示百分比。 v4: 数字表示像素,百分比需要显式字符串。

支持的单位:px%emremvhvw

- <Panel defaultSize={30} minSize={20} maxSize={60}>
+ <Panel defaultSize='30%' minSize='20%' maxSize='60%'>

- <Panel collapsedSize={5} collapsible>
+ <Panel collapsedSize='5%' collapsible>

警告: 如果直接升级不改 size 值,所有数字都会从"百分比"变成"像素",布局会完全错乱!

快速迁移规则: 在所有 defaultSizeminSizemaxSizecollapsedSize 的数值后加 % 并转为字符串。

Step 6: CSS Data 属性更新

v4 简化了 data 属性体系:

v3 属性v4 属性说明
data-panel-group-direction="horizontal"aria-orientation="vertical"语义翻转! v3=组方向,v4=分隔条方向
data-panel-group-direction="vertical"aria-orientation="horizontal"语义翻转! 水平分隔条在垂直组中
data-resize-handle-state="hover"data-separator="hover"简化
data-resize-handle-state="drag"data-separator="active"dragactive
data-resize-handle-state="inactive"data-separator="inactive"简化
data-resize-handle-activedata-separator="active"合并

Separator 的 data-separator 属性值: inactivehoveractivedisabled

关键陷阱: v3 的 data-panel-group-direction组的方向,v4 的 aria-orientation分隔条自身的方向。语义完全翻转!

  • 水平组 (orientation="horizontal"):分隔条是垂直的 → aria-orientation="vertical" → 需要 width
  • 垂直组 (orientation="vertical"):分隔条是水平的 → aria-orientation="horizontal" → 需要 height
  /* CSS 选择器更新 — 注意语义翻转! */
- [data-panel-group-direction="horizontal"] { width: 1px; cursor: col-resize; }
+ [aria-orientation="vertical"] { width: 1px; cursor: col-resize; }

- [data-panel-group-direction="vertical"] { height: 1px; cursor: row-resize; }
+ [aria-orientation="horizontal"] { height: 1px; cursor: row-resize; }

- [data-resize-handle-state="hover"] { ... }
+ [data-separator="hover"] { ... }

- [data-resize-handle-state="drag"] { ... }
+ [data-separator="active"] { ... }

- [data-resize-handle-active] { ... }
+ [data-separator="active"] { ... }

  /* Tailwind / 内联 data 属性 */
- className='data-[resize-handle-state=inactive]:opacity-20'
+ className='data-[separator=inactive]:opacity-20'

Step 7: Hook 变更

- import { useRef } from 'react';
- const panelRef = useRef<ImperativePanelHandle>(null);
- const groupRef = useRef<ImperativePanelGroupHandle>(null);
+ import { usePanelRef, useGroupRef } from 'react-resizable-panels';
+ const panelRef = usePanelRef();
+ const groupRef = useGroupRef();

  // autoSaveId 替代方案
+ import { useDefaultLayout } from 'react-resizable-panels';
+ const defaultLayout = useDefaultLayout({ groupId: 'my-layout', storage: localStorage });

Step 8: 其他移除

  // disableGlobalCursorStyles() 全局函数已移除
- import { disableGlobalCursorStyles } from 'react-resizable-panels';
- disableGlobalCursorStyles();
+ // 改为 Group 上的 prop
+ <Group disableCursor orientation='horizontal'>

常见错误快速定位

症状原因修复
PanelGroup is not exported组件重命名替换为 Group
PanelResizeHandle is not exported组件重命名替换为 Separator
direction is not a valid propprop 重命名替换为 orientation
布局完全错乱(面板极小/极大)尺寸单位变更数字加 % 后缀转字符串
CSS hover/drag 样式失效data 属性变更更新 CSS 选择器
order is not a valid propprop 已移除直接删除 order
onCollapse is not a valid propprop 已移除改用 onResize
autoSaveId is not a valid propprop 已移除改用 useDefaultLayout
PanelResizeHandleProps not found类型重命名替换为 SeparatorProps

迁移检查清单

  • 安装 v4: react-resizable-panels@4
  • PanelGroupGroup
  • PanelResizeHandleSeparator
  • directionorientation
  • 所有 size 数值加 % 后缀转字符串
  • 移除所有 order prop
  • onCollapse/onExpandonResize 回调
  • refpanelRef/groupRef 命名 prop
  • autoSaveIduseDefaultLayout hook
  • 更新 CSS: data-panel-group-directionaria-orientation
  • 更新 CSS: data-resize-handle-statedata-separator
  • 更新类型 import: PanelResizeHandlePropsSeparatorProps
  • 运行 typecheck 验证
  • 视觉验证布局和拖拽交互

完整迁移示例

Before (v3)

import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';

function MyLayout() {
  return (
    <PanelGroup direction='horizontal'>
      <Panel defaultSize={30} minSize={10} order={1}>
        <Sidebar />
      </Panel>
      <PanelResizeHandle className='w-1 bg-gray-300 hover:bg-blue-400' />
      <Panel defaultSize={70} minSize={30} order={2}>
        <Content />
      </Panel>
    </PanelGroup>
  );
}

After (v4)

import { Panel, Group, Separator } from 'react-resizable-panels';

function MyLayout() {
  return (
    <Group orientation='horizontal'>
      <Panel defaultSize='30%' minSize='10%'>
        <Sidebar />
      </Panel>
      <Separator className='w-1 bg-gray-300 hover:bg-blue-400' />
      <Panel defaultSize='70%' minSize='30%'>
        <Content />
      </Panel>
    </Group>
  );
}

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

tmux-session-manager

No summary provided by upstream source.

Repository SourceNeeds Review
General

wode-db-schema-pattern

No summary provided by upstream source.

Repository SourceNeeds Review
General

zustand-mutative-pattern

No summary provided by upstream source.

Repository SourceNeeds Review
General

wode-emittery-pattern

No summary provided by upstream source.

Repository SourceNeeds Review