### Install react-resizable-panels with npm Source: https://github.com/bvaughn/react-resizable-panels/blob/main/README.md Install the library from NPM to begin using it in your React project. ```sh npm install react-resizable-panels ``` -------------------------------- ### Install dependencies Source: https://github.com/bvaughn/react-resizable-panels/blob/main/CONTRIBUTING.md Installs project dependencies. ```shell pnpm install ``` -------------------------------- ### Panel with Resize Callback Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Shows how to use the 'onResize' callback to get real-time updates on a panel's size. The callback receives 'PanelSize' object with percentage and pixel values. ```typescript export function PanelWithCallback() { const [size, setSize] = useState(''); const handleResize = (panelSize: PanelSize) => { setSize(`${panelSize.asPercentage.toFixed(1)}% (${panelSize.inPixels}px)`); }; return ( <>
Current size: {size}
Resizable Panel Other Panel ); } ``` -------------------------------- ### Run documentation site locally Source: https://github.com/bvaughn/react-resizable-panels/blob/main/CONTRIBUTING.md Starts the documentation site on localhost port 3000. ```shell pnpm dev ``` -------------------------------- ### Get Panel Size Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Demonstrates how to retrieve the current size of a panel in both pixels and percentage using the `getSize()` method. The returned object contains `asPercentage` and `inPixels` properties. ```typescript const panelRef = useRef(null); function MyComponent() { const handleGetSize = () => { const size = panelRef.current?.getSize(); console.log(`Size: ${size?.asPercentage}% (${size?.inPixels}px)`); }; return ( <> Content ); } ``` -------------------------------- ### Get Panel Size Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/types.md Demonstrates how to retrieve the current size of a panel using its imperative handle. Ensure the panelRef is correctly assigned. ```typescript const panelRef = useRef(null); const handleGetSize = () => { const size = panelRef.current?.getSize(); console.log(`${size?.asPercentage}% (${size?.inPixels}px)`); // Output: "33.3% (400px)" }; ``` -------------------------------- ### Basic Two-Panel Layout Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/getting-started.md A practical example of a responsive two-panel layout using Group, Panel, and Separator. This is suitable for common sidebar and main content arrangements. ```typescript import { Group, Panel, Separator } from 'react-resizable-panels'; export function BasicLayout() { return (
Sidebar
Main Content
); } ``` -------------------------------- ### OnPanelResize Callback Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/types.md Example of implementing the onResize callback to log changes in panel size, including the panel's ID and its previous dimensions. The prevPanelSize will be undefined on initial mount. ```jsx { console.log(`Panel ${id} resized from ${prevSize?.inPixels}px to ${size.inPixels}px`); }} > Content ``` -------------------------------- ### Panel Size Format Options Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Examples demonstrating various formats for Panel size properties like defaultSize, minSize, and maxSize. ```typescript // Numeric: pixels defaultSize={300} // Percentage strings defaultSize="50%" defaultSize="33.33%" // Percentage numbers (no units) minSize={25} // 25% // Pixel strings minSize="100px" // Relative units minSize="1em" minSize="2rem" // Viewport units minSize="10vh" // 10% of viewport height minSize="5vw" // 5% of viewport width ``` -------------------------------- ### useDefaultLayout with Custom Storage Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Example of initializing useDefaultLayout with a custom storage implementation. ```typescript // Custom storage implementation const customStorage: LayoutStorage = { getItem: (key) => { /* ... */ }, setItem: (key, value) => { /* ... */ } }; useDefaultLayout({ id: 'my-layout', storage: customStorage }) ``` -------------------------------- ### useDefaultLayout with Default Storage Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Example of initializing useDefaultLayout with the default localStorage storage. ```typescript // Use localStorage (default) useDefaultLayout({ id: 'my-layout' }) ``` -------------------------------- ### Expand Panel Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Shows how to expand a collapsed panel using the `expand()` method. This is useful for restoring a panel's previous size after it has been collapsed. ```typescript const panelRef = useRef(null); function MyComponent() { const handleExpand = () => { panelRef.current?.expand(); }; return ( <> Content ); } ``` -------------------------------- ### Example: Larger Touch Targets for Resize Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Demonstrates how to increase the minimum hit target size for touch devices to improve accessibility. ```typescript {/* panels */} ``` -------------------------------- ### Basic Horizontal Layout Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-group.md Demonstrates a simple horizontal layout with two panels and a separator. ```typescript import { Group, Panel, Separator } from 'react-resizable-panels'; export function BasicLayout() { return (
Left Panel
Right Panel
); } ``` -------------------------------- ### Imperative Panel Control Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-group.md Demonstrates how to control panel layouts imperatively using `useRef` and `GroupImperativeHandle`. ```typescript import { Group, Panel, Separator } from 'react-resizable-panels'; import { useRef } from 'react'; import type { GroupImperativeHandle } from 'react-resizable-panels'; export function ImperativeControl() { const groupRef = useRef(null); const resetLayout = () => { groupRef.current?.setLayout({ panel1: 50, panel2: 50 }); }; const logLayout = () => { const layout = groupRef.current?.getLayout(); console.log('Layout:', layout); }; return ( <>
Panel 1 Panel 2 ); } ``` -------------------------------- ### Panel Size Properties Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/types.md Illustrates how to use different SizeUnits for panel properties like defaultSize, minSize, and maxSize. Numeric values for defaultSize are interpreted as pixels. ```jsx ``` -------------------------------- ### Run end-to-end tests locally Source: https://github.com/bvaughn/react-resizable-panels/blob/main/CONTRIBUTING.md Installs end-to-end test dependencies and runs the tests. ```shell pnpm prerelease pnpm e2e:install pnpm dev:integrations & pnpm e2e:test ``` -------------------------------- ### Panel with Size Constraints Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Illustrates setting minimum and maximum size constraints for a panel using pixel or percentage values. 'minSize' and 'maxSize' props are used. ```typescript export function ConstrainedPanel() { return ( Constrained Panel Other Panel ); } ``` -------------------------------- ### Collapse Panel Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Demonstrates how to collapse a panel programmatically using the `collapse()` method. Ensure the panel is marked as `collapsible` and has a `collapsedSize` defined. ```typescript const panelRef = useRef(null); function MyComponent() { const handleCollapse = () => { panelRef.current?.collapse(); }; return ( <> Content ); } ``` -------------------------------- ### useDefaultLayout with Session Storage Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Example of initializing useDefaultLayout to use sessionStorage for layout persistence. ```typescript // Use sessionStorage useDefaultLayout({ id: 'my-layout', storage: sessionStorage }) ``` -------------------------------- ### Resize Panel Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Shows various ways to resize a panel using the `resize()` method. It accepts numbers (pixels), pixel strings, percentage strings, relative units, and viewport units. ```typescript const panelRef = useRef(null); function MyComponent() { const handleResize = () => { // All of these are valid: panelRef.current?.resize(200); // 200 pixels panelRef.current?.resize("200px"); // 200 pixels panelRef.current?.resize(50); // 50% panelRef.current?.resize("50%"); // 50% panelRef.current?.resize("1rem"); // 1rem relative to font size panelRef.current?.resize("50vh"); // 50% of viewport height }; return ( <> Content ); } ``` -------------------------------- ### Vertical Layout with Callbacks Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-group.md Illustrates a vertical layout with `onLayoutChange` and `onLayoutChanged` callbacks to monitor layout updates. ```typescript export function VerticalWithCallbacks() { const handleLayoutChange = (layout: Layout) => { console.log('Layout changing:', layout); }; const handleLayoutChanged = (layout: Layout, meta: LayoutChangedMeta) => { console.log('Layout changed:', layout); console.log('User interaction:', meta.isUserInteraction); // Persist to storage here }; return ( Top Panel Bottom Panel ); } ``` -------------------------------- ### Update assets Source: https://github.com/bvaughn/react-resizable-panels/blob/main/CONTRIBUTING.md Updates generated docs and examples, and runs code formatting and linting. ```shell pnpm compile pnpm prettier pnpm lint ``` -------------------------------- ### Example of Mixed Size Units in Panels Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Demonstrates using mixed units for size constraints within a group of panels. ```typescript Mixed size constraints Also mixed ``` -------------------------------- ### Collapsible Panel Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/README.md Illustrates how to make a panel collapsible, allowing it to be collapsed to a specific size, such as zero. Useful for sidebars or elements that can be hidden. ```typescript Sidebar ``` -------------------------------- ### Importing Components, Hooks, and Types Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/README.md Provides a comprehensive guide to importing all necessary components, hooks, and types from the 'react-resizable-panels' library. Ensure these imports are present in your project files. ```typescript // Components import { Group, Panel, Separator } from 'react-resizable-panels'; // Hooks import { useGroupRef, useGroupCallbackRef, usePanelRef, usePanelCallbackRef, useDefaultLayout, isCoarsePointer } from 'react-resizable-panels'; // Types import type { GroupImperativeHandle, GroupProps, PanelImperativeHandle, PanelProps, SeparatorProps, Layout, PanelSize, Orientation, LayoutStorage, LayoutChangedMeta, SizeUnit, GroupResizeBehavior, } from 'react-resizable-panels'; ``` -------------------------------- ### Integrating React-Specific ESLint Plugins Source: https://github.com/bvaughn/react-resizable-panels/blob/main/integrations/vite/README.md Example of how to integrate eslint-plugin-react-x and eslint-plugin-react-dom into the ESLint configuration. ```javascript // eslint.config.js import reactX from 'eslint-plugin-react-x' import reactDom from 'eslint-plugin-react-dom' export default tseslint.config({ plugins: { // Add the react-x and react-dom plugins 'react-x': reactX, 'react-dom': reactDom, }, rules: { // other rules... // Enable its recommended typescript rules ...reactX.configs['recommended-typescript'].rules, ...reactDom.configs.recommended.rules, }, }) ``` -------------------------------- ### Panel with Imperative Control Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Demonstrates controlling a panel's size and state imperatively using a ref. The 'PanelImperativeHandle' provides methods like 'resize', 'collapse', and 'expand'. ```typescript import type { PanelImperativeHandle } from 'react-resizable-panels'; export function ImperativePanel() { const panelRef = useRef(null); return ( <>
Controlled Panel ); } ``` -------------------------------- ### Nested Layout Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/README.md Shows how to create complex layouts by nesting groups of panels within other panels. This allows for unlimited depth and intricate UI structures. ```typescript Left Top-right Bottom-right ``` -------------------------------- ### Implement Animated Panel Transitions Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/advanced-guide.md Create smooth animated transitions for panel resizing using `requestAnimationFrame` for custom animation loops. This example animates a panel to a target size over 300ms with an ease-in-out quadratic easing function. ```typescript export function AnimatedPanels() { const panelRef = usePanelRef(); const [animating, setAnimating] = useState(false); const animateResize = async (targetSize: number) => { setAnimating(true); const startTime = Date.now(); const duration = 300; // 300ms animation const startSize = panelRef.current?.getSize().asPercentage ?? 50; const animate = () => { const elapsed = Date.now() - startTime; const progress = Math.min(elapsed / duration, 1); const easeInOutQuad = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress; const currentSize = startSize + (targetSize - startSize) * easeInOutQuad; panelRef.current?.resize(currentSize); if (progress < 1) { requestAnimationFrame(animate); } else { setAnimating(false); } }; requestAnimationFrame(animate); }; return ( <> Animated Panel Other ); } ``` -------------------------------- ### Zustand Integration for Layout State Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/patterns-and-examples.md Integrate layout state management with Zustand using its persistence middleware. This example shows how to define a store and update the layout. ```typescript import { create } from 'zustand'; import { persist } from 'zustand/middleware'; const useLayoutStore = create( persist( (set) => ({ layout: undefined, setLayout: (layout) => set({ layout }), }), { name: 'layout-storage' } ) ); export function ZustandLayout() { const { layout, setLayout } = useLayoutStore(); return ( { if (meta.isUserInteraction) { setLayout(newLayout); } }} > {/* panels */} ); } ``` -------------------------------- ### Panel Resize Behavior Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/types.md Demonstrates using 'preserve-relative-size' for flexible panels and 'preserve-pixel-size' for fixed-size panels within a group. Note the constraint that at least one panel must use 'preserve-relative-size'. ```jsx {/* This panel shrinks/grows with group */} Flexible {/* This panel stays same pixel size */} Fixed ``` -------------------------------- ### Expanding ESLint Configuration with Type-Aware Rules Source: https://github.com/bvaughn/react-resizable-panels/blob/main/integrations/vite/README.md Example of how to extend the ESLint configuration to include type-aware lint rules for TypeScript projects. ```javascript export default tseslint.config({ extends: [ // Remove ...tseslint.configs.recommended and replace with this ...tseslint.configs.recommendedTypeChecked, // Alternatively, use this for stricter rules ...tseslint.configs.strictTypeChecked, // Optionally, add this for stylistic rules ...tseslint.configs.stylisticTypeChecked, ], languageOptions: { // other options... parserOptions: { project: ['./tsconfig.node.json', './tsconfig.app.json'], tsconfigRootDir: import.meta.dirname, }, }, }) ``` -------------------------------- ### Handle Storage Quotas with `useDefaultLayout` Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/advanced-guide.md If storage quotas are exceeded, consider using `sessionStorage` for temporary storage or implementing custom quota management. This example shows using `sessionStorage` to avoid quota issues. ```typescript try { localStorage.setItem('test', 'large-data'); } catch (e) { console.error('Storage quota exceeded:', e); } // Solution: Use sessionStorage or implement quota management const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'layout', storage: sessionStorage, // Clears on page close }); ``` -------------------------------- ### VS Code-Style Three-Panel Layout Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/patterns-and-examples.md This example mimics the VS Code editor layout, featuring a sidebar, main editor area, and a bottom panel. It utilizes nested groups for horizontal and vertical resizing and includes collapsible panels. ```typescript import { Group, Panel, Separator } from 'react-resizable-panels'; import { useDefaultLayout } from 'react-resizable-panels'; export function VSCodeLayout() { const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'vscode-layout', panelIds: ['sidebar', 'editor', 'panel'], }); return (
{/* Top menu bar */}
VS Code Layout
{/* Main resizable area */} {/* Sidebar */}

Explorer

  • 📁 src/
  • 📁 public/
  • 📄 package.json
{/* Editor area with nested vertical split */}
src/App.tsx
{/* Editor content */}
Terminal
npm run dev
{/* Side panel */}

Problem

No problems found
); } ``` -------------------------------- ### Get and Set Group Layout with useGroupRef Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/hooks-reference.md Use `useGroupRef` to get a ref for the Group component's imperative API. This allows you to programmatically get or set the layout of the panels. ```typescript import { Group, Panel, Separator, useGroupRef } from 'react-resizable-panels'; export function MyComponent() { const groupRef = useGroupRef(); const handleGetLayout = () => { const layout = groupRef.current?.getLayout(); console.log('Current layout:', layout); }; const handleResetLayout = () => { groupRef.current?.setLayout({ panel1: 50, panel2: 50 }); }; return ( <>
Panel 1 Panel 2 ); } ``` -------------------------------- ### Basic Panel Usage Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Demonstrates how to set up a basic resizable panel group with two panels and a separator. Ensure 'react-resizable-panels' is imported. ```typescript import { Group, Panel, Separator } from 'react-resizable-panels'; export function BasicPanel() { return (
Resizable Content
More Content
); } ``` -------------------------------- ### Development Server Commands Source: https://github.com/bvaughn/react-resizable-panels/blob/main/integrations/next/README.md Commands to run the development server using different package managers. ```bash npm run dev # or yarn dev # or pnpm dev # or bun dev ``` -------------------------------- ### Use usePanelCallbackRef in a Component Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/hooks-reference.md Demonstrates how to use the usePanelCallbackRef hook to get a ref for a Panel component and pass it to child controls for interaction. ```typescript import { Group, Panel, Separator, usePanelCallbackRef } from 'react-resizable-panels'; function PanelControls({ panelRef }) { return (
); } export function MyComponent() { const [panelRef, setPanelRef] = usePanelCallbackRef(); return ( <> Controlled Panel Other Panel ); } ``` -------------------------------- ### Get Group Layout Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-group.md Retrieves the current layout of the panels within a group. Use this to inspect the current state of panel sizes. ```typescript interface GroupImperativeHandle { getLayout(): { [panelId: string]: number }; setLayout(layout: { [panelId: string]: number }): Layout; } ``` ```typescript const groupRef = useRef(null); function MyComponent() { const handleGetLayout = () => { const layout = groupRef.current?.getLayout(); console.log('Current layout:', layout); // Output: { panel1: 33.33, panel2: 66.67 } }; return ( <> {/* panels */} ); } ``` -------------------------------- ### Check if Panel is Collapsed Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Illustrates how to check if a panel is currently collapsed using the `isCollapsed()` method. This returns a boolean value. ```typescript const panelRef = useRef(null); function MyComponent() { const checkCollapsed = () => { const collapsed = panelRef.current?.isCollapsed(); console.log('Is collapsed:', collapsed); }; return ( <> Content ); } ``` -------------------------------- ### Responsive Layout Based on Screen Size Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/README.md Demonstrates how to create a responsive layout that adjusts its orientation based on screen size (e.g., mobile vs. desktop). Use this to adapt layouts for different devices. ```typescript {/* panels */} ``` -------------------------------- ### Basic Layout Persistence with localStorage Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/hooks-reference.md Demonstrates how to use the useDefaultLayout hook to save and restore panel layouts using localStorage. This is useful for maintaining user-defined panel sizes across sessions. ```typescript import { Group, Panel, Separator, useDefaultLayout } from 'react-resizable-panels'; export function PersistentLayout() { const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'my-layout', storage: localStorage, }); return ( Left Panel Right Panel ); } ``` -------------------------------- ### Disabled Separator Example Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-separator.md Disables user interaction with the separator using the `disabled` prop. A checkbox controls the disabled state of the separator. ```typescript import { useState } from 'react'; import { Group, Panel, Separator } from 'react-resizable-panels'; export function DisabledSeparator() { const [separatorDisabled, setSeparatorDisabled] = useState(false); return ( <> Left Right ); } ``` -------------------------------- ### PanelImperativeHandle Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/types.md Provides an imperative API for controlling Panel components, including methods to collapse, expand, get size, check collapsed state, and resize. ```APIDOC ## PanelImperativeHandle ### Description Imperative API for Panel component. ### Interface Definition ```typescript interface PanelImperativeHandle { collapse(): void; expand(): void; getSize(): { asPercentage: number; inPixels: number }; isCollapsed(): boolean; resize(size: number | string): void; } ``` ### Methods - `collapse()`: Collapse panel to `collapsedSize` (if collapsible). - `expand()`: Expand collapsed panel to previous size. - `getSize()`: Get current size in percentage and pixels. - `isCollapsed()`: Check if panel is collapsed. - `resize(size)`: Set panel size (supports all size formats). ``` -------------------------------- ### Apply Dynamic Size Constraints Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/advanced-guide.md Implement responsive panel sizing by dynamically adjusting `minSize` and `maxSize` props based on window dimensions. Requires a `useEffect` hook to track window resize events. ```typescript export function ResponsiveConstraints() { const [windowWidth, setWindowWidth] = useState(window.innerWidth); useEffect(() => { const handleResize = () => setWindowWidth(window.innerWidth); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); const minSidebarSize = windowWidth < 768 ? '60px' : '150px'; const maxSidebarSize = windowWidth < 768 ? '120px' : '400px'; return ( Sidebar Main ); } ``` -------------------------------- ### Desktop-Friendly Group Configuration Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Configure a Group component for desktop usage with `resizeTargetMinimumSize` optimized for mouse and trackpad precision. Panels have specific default and minimum sizes. ```typescript Sidebar Content ``` -------------------------------- ### Strict Size Constraints with Fixed and Flexible Panels Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Configure panels with strict size constraints, including a fixed-size panel using `minSize` and `maxSize` set to the same value, and a flexible panel that can grow to fill available space. ```typescript Fixed Width Sidebar Flexible Content ``` -------------------------------- ### Documentation File Structure Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/README.md This snippet shows the directory structure of the project's documentation files. Each file corresponds to a specific aspect of the library. ```markdown /output/ ├── README.md (this file) ├── getting-started.md (introduction) ├── api-reference-group.md (Group component) ├── api-reference-panel.md (Panel component) ├── api-reference-separator.md (Separator component) ├── hooks-reference.md (all hooks) ├── types.md (type definitions) ├── configuration.md (options and config) ├── patterns-and-examples.md (real-world patterns) └── advanced-guide.md (troubleshooting, advanced) ``` -------------------------------- ### Next.js App Router Layout Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Configure layout for Next.js App Router by marking the component as a Client Component and using `useDefaultLayout`. No special `panelIds` are required for basic setup. ```typescript 'use client'; // Mark as Client Component import { Group, Panel, Separator, useDefaultLayout } from 'react-resizable-panels'; export function AppLayout() { const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'nextjs-layout', }); return ( {/* panels */} ); } ``` -------------------------------- ### Use usePanelRef for Imperative Panel Control Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/hooks-reference.md Demonstrates how to use the usePanelRef hook to get a ref for a Panel component and call its imperative methods like resize, getSize, collapse, expand, and isCollapsed. ```typescript import { Group, Panel, Separator, usePanelRef } from 'react-resizable-panels'; export function MyComponent() { const panelRef = usePanelRef(); const handleResize = () => { panelRef.current?.resize('300px'); }; const handleGetSize = () => { const size = panelRef.current?.getSize(); console.log(`Size: ${size?.asPercentage}% (${size?.inPixels}px)`); }; const handleCollapse = () => { panelRef.current?.collapse(); }; const handleExpand = () => { panelRef.current?.expand(); }; const checkCollapsed = () => { const isCollapsed = panelRef.current?.isCollapsed(); console.log('Collapsed:', isCollapsed); }; return ( <>
Controlled Panel Other Panel ); } ``` -------------------------------- ### Basic Separator Usage Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-separator.md Demonstrates the basic implementation of a horizontal separator between two panels. Ensure 'react-resizable-panels' is imported. ```typescript import { Group, Panel, Separator } from 'react-resizable-panels'; export function BasicSeparator() { return (
Left Panel
Right Panel
); } ``` -------------------------------- ### Panel Component Configuration Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/getting-started.md Shows how to configure a single Panel with various props like size constraints, collapsible behavior, and an ID. Use this to define individual content areas within a group. ```typescript Panel Content ``` -------------------------------- ### Server-Rendering Safe Layout Persistence Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/hooks-reference.md Demonstrates a server-rendering safe approach for layout persistence using useDefaultLayout. The hook's internal use of `useSyncExternalStore` handles client-only storage like localStorage without causing hydration mismatches. ```typescript export function ServerSafeLayout() { const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'ssr-layout', // useSyncExternalStore prevents hydration mismatch when storage // is client-only (e.g., localStorage) }); return ( Left Right ); } ``` -------------------------------- ### Persistent Layout with State Management Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/README.md Shows how to implement a persistent layout that saves and restores its state. Use this when user layout preferences need to be maintained across sessions. ```typescript const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'layout' }); {/* panels */} ``` -------------------------------- ### Synchronize Layouts Between Panel Groups Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/patterns-and-examples.md Enable two separate panel groups to share the same layout configuration. A button click triggers a sync, applying the layout from one group to another using `getLayout` and `setLayout`. ```typescript export function SynchronizedLayouts() { const layout1Ref = useGroupRef(); const layout2Ref = useGroupRef(); const syncLayout = () => { const layout = layout1Ref.current?.getLayout(); if (layout) { layout2Ref.current?.setLayout(layout); } }; return ( <>

Layout 1

Panel A1 Panel B1

Layout 2

Panel A2 Panel B2
); } ``` -------------------------------- ### Run unit tests locally Source: https://github.com/bvaughn/react-resizable-panels/blob/main/CONTRIBUTING.md Executes unit tests for the project. ```shell pnpm test ``` -------------------------------- ### Mobile-Friendly Group Configuration Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Configure a Group component for touch devices with larger `resizeTargetMinimumSize` values for 'coarse' (touch) input. Includes fallback for 'fine' (mouse) input. ```typescript Panel 1 Panel 2 ``` -------------------------------- ### resize() Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/api-reference-panel.md Updates the panel's size. Accepts various size formats including numeric pixels, percentage strings, pixel strings, relative units, and viewport units. ```APIDOC ## resize() ### Description Updates the panel's size. Accepts multiple size formats. ### Signature ```typescript resize(size: number | string): void ``` ### Parameters - `size`: New panel size in any supported format: - Numeric values are assumed to be pixels - Strings without units are assumed to be percentages (e.g., "33") - Percentage strings: "50%" - Pixel strings: "200px" - Relative units: "1rem", "2em" - Viewport units: "50vh", "25vw" ### Example ```typescript const panelRef = useRef(null); function MyComponent() { const handleResize = () => { // All of these are valid: panelRef.current?.resize(200); // 200 pixels panelRef.current?.resize("200px"); // 200 pixels panelRef.current?.resize(50); // 50% panelRef.current?.resize("50%"); // 50% panelRef.current?.resize("1rem"); // 1rem relative to font size panelRef.current?.resize("50vh"); // 50% of viewport height }; return ( <> Content ); } ``` ``` -------------------------------- ### Handle Empty Layouts with Missing Panel IDs Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/advanced-guide.md Demonstrates how the library handles `Layout` objects where panel IDs might be missing. The library automatically assigns sizes to the remaining panels. ```typescript const layout: Layout = { left: 50, // right panel ID missing }; Left Right {/* Gets auto-assigned size */} ``` -------------------------------- ### useDefaultLayout Options Reference Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Configuration options for the useDefaultLayout hook. Specify layout ID, storage, panel IDs, and save behavior. ```typescript useDefaultLayout({ // Required: one of id or groupId id?: string; // Preferred: unique layout identifier groupId?: string; // Deprecated: use 'id' instead // Optional: persistence configuration storage?: LayoutStorage; // Default: localStorage // Optional: conditional panel support panelIds?: string[]; // Panel IDs for conditional rendering // Optional: save behavior onlySaveAfterUserInteractions?: boolean; // Default: false // Deprecated: debounce configuration debounceSaveMs?: number; // Default: 100ms (deprecated) }) ``` -------------------------------- ### Layout Persistence with Custom Storage Implementation Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/hooks-reference.md Illustrates using a custom storage object with useDefaultLayout, such as cookie-based storage. The custom storage must implement getItem and setItem methods compatible with the hook's expectations. ```typescript // Example: cookie-based storage const cookieStorage = { getItem: (key: string) => { const cookies = document.cookie.split(';'); for (const cookie of cookies) { const [name, value] = cookie.trim().split('='); if (name === key) return decodeURIComponent(value); } return null; }, setItem: (key: string, value: string) => { document.cookie = `${key}=${encodeURIComponent(value)};path=/`; } }; export function CookieStorageLayout() { const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'cookie-layout', storage: cookieStorage, }); return ( Left Right ); } ``` -------------------------------- ### Test Panel Resizing with User Events Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/patterns-and-examples.md Use `@testing-library/user-event` to simulate user interactions like dragging a separator to test panel resizing functionality. Ensure the layout changes as expected after the interaction. ```typescript import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; describe('ResizablePanel', () => { it('resizes panels via separator', async () => { const { getByTestId } = render( Left Right ); const separator = getByTestId('sep'); // Simulate drag await userEvent.pointer({ keys: '[MouseLeft>]', target: separator, coords: { x: 100, y: 0 }, }); // Verify layout changed const layout = /* get from component */ {}; expect(layout.left).not.toBe(50); }); }); ``` -------------------------------- ### useDefaultLayout with Conditional Panels Source: https://github.com/bvaughn/react-resizable-panels/blob/main/_autodocs/configuration.md Demonstrates configuring useDefaultLayout for conditionally rendered panels by specifying all possible panel IDs. ```typescript const { defaultLayout, onLayoutChanged } = useDefaultLayout({ id: 'conditional-layout', panelIds: ['sidebar', 'main', 'footer'], // All possible panels }); // Can now conditionally render any combination {showSidebar && ( <> Sidebar )} Main Footer ```