Home > OS >  Make a draggable split panel like the console of CodeSandbox
Make a draggable split panel like the console of CodeSandbox

Time:12-27

I would like to make a draggable split panel for an editor. Its behavior is mainly like Console panel of CodeSandbox:

  1. When we click on Console, the panel is expanded, and the arrow becomes ArrowDown for closing.
  2. The border of the panel is dragabble.
  3. When we click on Console on an expanded panel, the panel is closed, and the arrow becomes ArrowUp for expanding.

I have the following code (https://codesandbox.io/s/reset-forked-ivebxf?file=/src/App.js) by https://github.com/johnwalley/allotment. It can expand and close the panel, but there is a conflict with resizing. When the panel is closed, we drag the border up, I would like the arrow to become ArrowDown. Similarly, when the panel is open, we drag the border down to the bottom, I would like the arrow to be ArrowUp.

Does anyone know how to do so? I'm open to other react libraries too.

import React from "react";
import { Allotment } from "allotment";
import "allotment/dist/style.css";
import styles from "./App.module.css";

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      toExpand: true
    };
  }

  render() {
    return (
      <div>
        <div className={styles.container}>
          <Allotment vertical>
            <Allotment.Pane>abc</Allotment.Pane>
            {!this.state.toExpand && (
              <Allotment.Pane preferredSize="50%">
                <div
                  onClick={() => {
                    this.setState({ toExpand: !this.state.toExpand });
                  }}
                >
                  Console &nbsp;
                  {this.state.toExpand ? "ArrowUp" : "ArrowDown"}
                </div>
              </Allotment.Pane>
            )}
            {this.state.toExpand && (
              <Allotment.Pane preferredSize="0%">
                <div
                  onClick={() => {
                    this.setState({ toExpand: !this.state.toExpand });
                  }}
                >
                  Console &nbsp;
                  {this.state.toExpand ? "ArrowUp" : "ArrowDown"}
                </div>
              </Allotment.Pane>
            )}
          </Allotment>
        </div>
      </div>
    );
  }
}

CodePudding user response:

You can use onChange callback function of Allotment component. My solution is as follows:

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      toExpand: true
    };
    this.myRef = React.createRef();
  }

  handleChange = (sizes) => {
    if (sizes.length > 1) {
      if (sizes[1] < 31) {
        this.setState({ toExpand: true });
      } else {
        this.setState({ toExpand: false });
      }
    }
  };

  render() {
    return (
      <div>
        <div className={styles.container}>
          <Allotment vertical onChange={this.handleChange} ref={this.myRef}>
            <Allotment.Pane>Main Area</Allotment.Pane>
            <Allotment.Pane preferredSize="0%">
              <div
                onClick={() => {
                  if (this.state.toExpand) {
                    this.myRef.current.resize([50, 50]);
                  } else {
                    this.myRef.current.resize([10000, 0]);
                  }
                }}
              >
                Console &nbsp;
                {this.state.toExpand ? "ArrowUp" : "ArrowDown"}
              </div>
            </Allotment.Pane>
          </Allotment>
        </div>
      </div>
    );
  }
}

CodePudding user response:

<Allotment onChange={}/> component has an onChange event to identity each changes. You have to make one trigger point (400 in my case or you can calculate as per window height) and change value of Arrow Mark

<Allotment vertical onChange={this.changeSize}>

changeSize = (e) => {
    if (e[0] > 400) { // use your desired trigger
      console.log(e[0]);
      this.setState({ toExpand: !this.state.toExpand });
    }
  };
  • Related