Hone logo
Hone
Problems

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:

  1. Two Child Panes: The SplitPane component should render two distinct child elements. These children will represent the content of each pane.
  2. 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.
  3. 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.
  4. Dynamic Resizing: As the splitter is dragged, the dimensions of the two child panes should update in real-time.
  5. 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.
  6. 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 SplitPane has 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 600px width and 300px height.
    • A draggable splitter positioned vertically in the middle.
    • Initially, Pane 1 occupies 300px width and Pane 2 occupies 300px width.
    • Dragging the splitter to the right increases Pane 1's width and decreases Pane 2's width, and vice-versa.

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 500px width and 400px height.
    • A draggable splitter positioned horizontally in the middle.
    • Initially, Pane 1 occupies 100px height and Pane 2 occupies 300px height.
    • Dragging the splitter downwards increases Pane 1's height and decreases Pane 2's height, and vice-versa.

Constraints

  • The SplitPane component must be implemented using React and TypeScript.
  • The component should be performant, with smooth updates during dragging. Avoid unnecessary re-renders.
  • The orientation prop should accept "vertical" or "horizontal".
  • The initialFirstPaneSize prop should accept a number representing pixels.
  • The component must accept exactly two direct children.

Notes

  • Consider using state management within the SplitPane component to track the current size of the panes.
  • Event handling for mousedown, mousemove, and mouseup will 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 orientation prop.
  • For simplicity, you can assume the SplitPane component will have explicit width and height styles or be placed within a container that provides them.
Loading editor...
typescript