Hone logo
Hone
Problems

React Split Pane Component

This challenge asks you to implement a reusable split pane component in React using TypeScript. Split pane components are commonly used in applications to divide a screen into two or more resizable panels, allowing users to customize the layout and focus on different sections of content simultaneously. This is a valuable skill for building flexible and user-friendly interfaces.

Problem Description

You need to create a SplitPane component that allows users to resize a dividing line between two child components (panes). The component should:

  • Accept two child components: These represent the content to be displayed in each pane.
  • Provide a resizable divider: A visual element (e.g., a line) that the user can drag to adjust the size of the panes.
  • Maintain state for pane sizes: The component should track the width (or height, if vertical) of each pane.
  • Handle resizing: When the user drags the divider, the component should update the pane sizes accordingly.
  • Provide a minimum and maximum pane size: Prevent panes from becoming too small or too large.
  • Support both horizontal and vertical orientations: The component should be configurable to split the screen horizontally (default) or vertically.

Expected Behavior:

  • Initially, the split pane should have a default size distribution (e.g., 50/50).
  • Dragging the divider should smoothly update the pane sizes.
  • The divider should visually indicate its draggable state (e.g., change cursor on hover).
  • The component should prevent the panes from exceeding the specified minimum or maximum sizes.
  • The component should re-render correctly when the pane sizes change.

Edge Cases to Consider:

  • What happens if one of the child components has dynamic content that affects its size?
  • How should the component handle invalid input (e.g., null or undefined children)?
  • Consider accessibility - ensure the divider is focusable and keyboard navigable.

Examples

Example 1: Horizontal Split (Default)

Input: <SplitPane><Panel>Left Pane</Panel><Panel>Right Pane</Panel></SplitPane>
Output: A horizontal split pane with "Left Pane" occupying 50% of the width and "Right Pane" occupying the other 50%.  The divider is draggable.
Explanation: The component defaults to a horizontal split and divides the space equally.

Example 2: Vertical Split

Input: <SplitPane orientation="vertical"><Panel>Top Pane</Panel><Panel>Bottom Pane</Panel></SplitPane>
Output: A vertical split pane with "Top Pane" occupying 50% of the height and "Bottom Pane" occupying the other 50%. The divider is draggable.
Explanation: The `orientation="vertical"` prop changes the split direction.

Example 3: Minimum and Maximum Sizes

Input: <SplitPane minSize={100} maxSize={800}><Panel>Pane 1</Panel><Panel>Pane 2</Panel></SplitPane>
Output: A horizontal split pane where each pane initially occupies 50% of the available width.  Dragging the divider will not allow either pane to be smaller than 100px or larger than 800px.
Explanation: The `minSize` and `maxSize` props enforce size limits.

Constraints

  • Component Structure: The component should be a functional component using React Hooks.
  • Styling: You can use CSS or a CSS-in-JS library (e.g., styled-components) for styling. Focus on functionality over elaborate styling.
  • Performance: The component should be performant and avoid unnecessary re-renders. Use useMemo and useCallback where appropriate.
  • Pane Size Range: minSize and maxSize should be numbers representing pixel values.
  • Orientation: The orientation prop should be a string, either "horizontal" (default) or "vertical".

Notes

  • Consider using useState to manage the pane sizes and divider position.
  • You'll need to handle mouse events (e.g., onMouseDown, onMouseMove, onMouseUp) to implement the dragging functionality.
  • Think about how to calculate the new pane sizes based on the divider's position and the available space.
  • Accessibility is important. Make sure the divider is focusable and can be interacted with using the keyboard.
  • You can assume that the parent container of the SplitPane component has a defined width (for horizontal splits) or height (for vertical splits).
Loading editor...
typescript