react-window-splitter

Collapsible

You can mark a panel as collapsible by using the collapsible prop. By default the panel will collapse to 0px when collapsed. You can control this by using the collapsedSize prop.

import { PanelGroup, Panel, PanelResizer } from "react-window-splitter";

function CollapsibleExample() {
  return (
    <PanelGroup>
      <Panel collapsible collapsedSize="100px" min="150px" max="400px" />
      <PanelResizer />
      <Panel min="130px" />
    </PanelGroup>
  );
}

Default Collapsed

If you want the panel to start collapsed by default you can use the defaultCollapsed prop.

Controlled

If you want to control the collapsed state of the panel you can use the imperative API or you can have full control over the collapsed state by using the collapsed and onCollapseChange props.

import { useState } from "react";
import { PanelGroup, Panel, PanelResizer } from "react-window-splitter";

function CollapsibleExample() {
  const [collapsed, setCollapsed] = useState(true);

  const onCollapseChange = (isCollapsed: boolean) => {
    // Do whatever logic you want here.
    // If you don't change the collapsed state, the panel
    // will not collapse.
    const shouldSetValue = true;

    if (shouldSetValue) {
      setCollapsed(isCollapsed);
    }
  };

  return (
    <PanelGroup>
      <Panel
        min="150px"
        max="400px"
        collapsible
        collapsedSize="100px"
        collapsed={collapsed}
        onCollapseChange={onCollapseChange}
      />
      <PanelResizer />
      <Panel min="130px" />
    </PanelGroup>
  );
}

Animated Collapse

You can animate the collapse/expand by using the collapseAnimation prop.

The component support 3 basic animations:

  • ease-in-out
  • bounce
  • linear

You can also customize the duration by providing and object to the collapseAnimation prop. Try focus one of the resizer handles and pressing Enter to see the animation in action.

import { PanelGroup, Panel, PanelResizer } from "react-window-splitter";

function CollapsibleExample() {
  return (
    <PanelGroup>
      <Panel
        min="150px"
        max="400px"
        collapsible
        collapsedSize="100px"
        collapseAnimation={{
          easing: "ease-in-out",
          duration: 1000,
        }}
      />
      <PanelResizer />
      <Panel min="130px" />
    </PanelGroup>
  );
}

Custom Easing Function

You can completely customize the easing function by providing a function to the collapseAnimation prop.

The function provided to ease takes a number t that represent the progress of the animation in the range of [0, 1]. The return value of the function should be a number between [0, 1] that represents the altered progress of the animation.

Some good libraries you can use to create your own easing function are:

1
2
import { PanelGroup, Panel, PanelResizer } from "react-window-splitter";
import { spring } from "framer-motion";
import { useMemo } from "react";

function CollapsibleExample() {
  const springFn = useMemo(() => {
    return spring({
      keyframes: [0, 1],
      velocity: 0.0,
      stiffness: 100,
      damping: 10,
      mass: 1.0,
      duration: 1000,
    });
  }, []);

  return (
    <PanelGroup>
      <Panel
        min="150px"
        max="400px"
        collapsible
        collapsedSize="100px"
        collapseAnimation={{
          easing: (t) => springFn.next(t * 1000).value,
          duration: springFn.calculatedDuration ?? 1000,
        }}
      />
      <PanelResizer />
      <Panel min="130px" />
    </PanelGroup>
  );
}