Implement a Resizable Split Pane Component in React
This challenge asks you to build a fundamental UI component commonly found in modern applications: a resizable split pane. This component allows users to divide a screen or container into two (or more) resizable sections, adjusting the proportion of space allocated to each. This is incredibly useful for layouts where users need to view and interact with multiple related content areas simultaneously, like code editors with a file explorer, or dashboards with different data visualizations.
Problem Description
You need to create a React component, SplitPane, that accepts two child elements and allows the user to resize the division between them by dragging a splitter.
Key Requirements:
- Two Child Panes: The
SplitPanecomponent should render two distinct child elements. These children will represent the content of each pane. - Vertical or Horizontal Split: The component should support both vertical (side-by-side) and horizontal (top-bottom) splitting. This can be controlled via a prop.
- Resizable Splitter: A draggable "splitter" or "handle" should be rendered between the two panes. Users can click and drag this splitter to change the relative widths (for vertical splits) or heights (for horizontal splits) of the two panes.
- Dynamic Resizing: As the splitter is dragged, the dimensions of the two child panes should update in real-time.
- Initial Size Control: The component should allow for an initial distribution of space, perhaps through a prop that defines the initial size of one of the panes.
- Responsiveness: The component should ideally handle its parent container's resizing gracefully.
Expected Behavior:
- When the user clicks and drags the splitter, the boundary between the two panes moves.
- The sum of the dimensions (width for vertical, height for horizontal) of the two panes should remain constant and equal to the available space within the
SplitPane's container. - The component should work within a standard React application structure.
Edge Cases:
- What happens if the
SplitPanehas no children or only one child? (For this challenge, assume valid input of two children). - What happens if the parent container has no explicit dimensions?
- Minimum and maximum sizes for panes could be considered, though not strictly required for the initial implementation.
Examples
Example 1: Vertical Split
Let's say the SplitPane has a fixed width of 600px and height of 300px.
-
Input (Props and Children):
orientation="vertical"initialFirstPaneSize={300}(pixels)- Child 1:
<div style={{ backgroundColor: 'lightblue', padding: '20px' }}>Pane 1</div> - Child 2:
<div style={{ backgroundColor: 'lightgreen', padding: '20px' }}>Pane 2</div>
-
Output (Rendered Structure and Behavior):
- A container of
600pxwidth and300pxheight. - A draggable splitter positioned vertically in the middle.
- Initially, Pane 1 occupies
300pxwidth and Pane 2 occupies300pxwidth. - Dragging the splitter to the right increases Pane 1's width and decreases Pane 2's width, and vice-versa.
- A container of
Example 2: Horizontal Split
Let's say the SplitPane has a fixed width of 500px and height of 400px.
-
Input (Props and Children):
orientation="horizontal"initialFirstPaneSize={100}(pixels)- Child 1:
<div style={{ backgroundColor: 'salmon', padding: '20px' }}>Header</div> - Child 2:
<div style={{ backgroundColor: 'khaki', padding: '20px' }}>Content Area</div>
-
Output (Rendered Structure and Behavior):
- A container of
500pxwidth and400pxheight. - A draggable splitter positioned horizontally in the middle.
- Initially, Pane 1 occupies
100pxheight and Pane 2 occupies300pxheight. - Dragging the splitter downwards increases Pane 1's height and decreases Pane 2's height, and vice-versa.
- A container of
Constraints
- The
SplitPanecomponent must be implemented using React and TypeScript. - The component should be performant, with smooth updates during dragging. Avoid unnecessary re-renders.
- The
orientationprop should accept"vertical"or"horizontal". - The
initialFirstPaneSizeprop should accept a number representing pixels. - The component must accept exactly two direct children.
Notes
- Consider using state management within the
SplitPanecomponent to track the current size of the panes. - Event handling for
mousedown,mousemove, andmouseupwill be crucial for implementing the drag functionality. - CSS positioning and dimensions will be key to achieving the desired layout and resizing behavior.
- Think about how to calculate the sizes correctly based on the
orientationprop. - For simplicity, you can assume the
SplitPanecomponent will have explicitwidthandheightstyles or be placed within a container that provides them.