Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set initial size and memorize last size of allotments

Tags:

css

reactjs

panel

I have made a draggable split panel by https://github.com/johnwalley/allotment.

I would like to realize several things:

  1. Clicking on Expand or collapse the allotment B will expand or collapse the allotment B.
  2. We can drag the splitter, the position of the splitter is saved before collapsing the allotment B so that we can go back to that position when expanding allotment B.
  3. The first time when we expand the allotment B, I would like the height of the allotment B to be 1/5 of the entire height.

I wrote the code as follows (https://codesandbox.io/s/reset-forked-f2f386?file=/src/App.js). I could not realize 2) and 3) at the same time.

Does anyone know why it's like that?

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

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

  handleChangeAllotment = (sizes) => {
    if (sizes.length > 1) {
      if (sizes[1] < 31) {
        this.setState({ toExpand: true });
      } else {
        this.setState({
          toExpand: false,
          lastExpandedSize: sizes // removing this line will set the initial sizes correctly, but will not be able to save last sizes.
        });
      }
    }
  };

  undertakeExpandOrCollapse = () => {
    if (this.state.toExpand) {
      this.myRef.current.resize(this.state.lastExpandedSize);
    } else {
      this.myRef.current.resize([10000, 0]);
    }
  };

  render() {
    return (
      <div
        style={{
          minWidth: 200,
          height: "100vh",
          overflowX: "auto",
          width: "auto",
          margin: "0px 0px 0px 0px"
        }}
      >
        <Allotment
          vertical
          onChange={this.handleChangeAllotment}
          ref={this.myRef}
        >
          <Allotment.Pane>
            <span onClick={this.undertakeExpandOrCollapse}>
              Expand or collapse the allotment B
            </span>
          </Allotment.Pane>
          <Allotment.Pane preferredSize="0%" minSize={30}>
            the allotment B
          </Allotment.Pane>
        </Allotment>
      </div>
    );
  }
}
like image 202
SoftTimur Avatar asked Sep 06 '25 21:09

SoftTimur


1 Answers

My quick idea is that by default, there is no saved value, and the value of lastExpandedSize is null. Sensing this, we pass one-fifth of the screen height as the saved height. When closing, there will already be a saved value, so the useState function will return that value from then on.

// ...

constructor(props) {
  super(props);
  this.state = {
    toExpand: true,
    lastExpandedSize: null // set null to default
  };
  this.containerRef = React.createRef();
  this.myRef = React.createRef();
}

/**
 * Check to has LastExpandedSize
 * @return {bool}
 */
hasLastExpandedSize = () => {
  return this.state.lastExpandedSize !== null;
}

/**
 * Get DefaultExpandedSize
 * @param {number} ratio
 * @param {number} height
 * @return {number[]}
 */
getDefaultExpandedSize = (ratio = 5, height = 0) => {
  if (height < 1) {
    height = this.containerRef.current.clientHeight;
  }

  return [
    height * (ratio - 1) / ratio, 
    height / ratio
  ];
}

handleChangeAllotment = (sizes) => {
  if (sizes.length > 1) {
    if (sizes[1] < 31) {
      this.setState({ toExpand: true });
    }
    else {
      this.setState({
        toExpand: false,
        lastExpandedSize: this.hasLastExpandedSize()
          ? sizes
          : this.getDefaultExpandedSize()
      });
    }
  }
};

// ...
<div
  ref={this.containerRef}
  style={{
    minWidth: 200,
    height: "100vh",
    overflowX: "auto",
    width: "auto",
    margin: "0px 0px 0px 0px"
  }}
>
  ...
</div>
like image 145
rozsazoltan Avatar answered Sep 08 '25 10:09

rozsazoltan