React resizable only resizing the width of the box, not the height

Viewed 5693

I have a React-mui draggable dialog component on which I am using resizable box:

return (
  <StyledDialog
    open={open}
    classes={{root: classes.dialog, paper: classes.paper}}
    PaperComponent={PaperComponent}
    aria-labelledby="draggable-dialog"
  >
    <ResizableBox
      height={520}
      width={370}
      minConstraints={[300, 500]}
      maxConstraints={[Infinity, Infinity]}
      className={classes.resizable}
    >
      <DialogContent classes={{root: classes.dialogContent}} id="draggable-dialog">
        <IconButton className={classes.clearIcon} aria-label="Clear" onClick={onClose}>
          <ClearIcon/>
        </IconButton>
        <iframe
          src={hjelpemiddel.url}
          title={hjelpemiddel.navn}
          width="100%"
          height="100%">
        </iframe>
      </DialogContent>
    </ResizableBox>
  </StyledDialog>
);

I would like to resize the iframe inside the dialog along with the ResizableBox. But, it seems I can only resize the width of the ResizableBox, and not the height of the box, at least the maximum height seems to be the one that is set initially. How can I fix that, so that I can resize the height as well?

UPDATE

Codesanbox is available here.

FYI, for some reason sometimes import fail message appears, but everything works fine if you refresh the page of the codesandbox.

3 Answers

In your CodeSandBox, based on my testing, the events for dragging & resizing are simultaneously firing. You could use the cancel prop of react-draggable so that the dragging would not occur when the resize handle is the component being interacted with.

<Draggable
  cancel={".react-resizable-handle"}
    ...

When you do this, the draggable element will not be updating its CSS transform: translate property anymore while resizing - for this, you can opt to control your Draggable component's position. Translate/Set X & Y as necessary to retain its position while resizing. Note that the x & y state & state setters should be residing on a common parent/ancestor among these components that you will be passing down as props.

export default function App() {
  // have the source of truth for the positions on a common parent/ancestor
  const [x, setX] = React.useState(0);
  const [y, setY] = React.useState(0);

  return (
    <div className="App">
      <PDFDialog x={x} y={y} setX={setX} setY={setY} />
    </div>
  );
}

...

class PDFDialog extends React.Component {
  state = {
    open: true
  };

  render() {
    const { open } = this.state;
    const { classes } = this.props;

    return (
      <StyledDialog
        open={open}
        classes={{ root: classes.dialog, paper: classes.paper }}
        PaperComponent={PaperComponent}
        aria-labelledby="draggable-dialog"
        PaperProps={{
          x: this.props.x,
          y: this.props.y,
          setX: this.props.setX,
          setY: this.props.setY
        }}
      >
        <ResizableBox
          height={520}
          width={370}
          minConstraints={[300, 500]}
          maxConstraints={[Infinity, Infinity]}
          className={classes.resizable}
          onResize={(e) => {
            if (e.movementX !== 0) {
              this.props.setX((prev) => prev + e.movementX);
            } else if (e.movementY !== 0) {
              this.props.setY((prev) => prev + e.movementY / 2);
            }
          }}
        ></ResizableBox>

        ...

// refactored draggable component:
<Draggable
  position={{ x: x, y: y }}
  cancel={".react-resizable-handle"} // <-- cancel the dragging if resize is interacted with
  onDrag={(e) => {
    if (e.movementX !== 0) {
      setX((prev) => prev + e.movementX);
    }
    if (e.movementY !== 0) {
      setY((prev) => prev + e.movementY);
    }
  }}
>
  <Paper {...props} />
</Draggable>

Edit React MUI + Draggable + Resizable Component

(On my CodeSandBox, I've gotten rid of constraints such as minimum height & width to clearly show the example)

You can bind the event of resize of window, calculate the new height and width and pass it to the resizable-box of yours

object.addEventListener("resize", function() {
//Here you can write logic to apply resizing on the resizable-box
});

Obviously, react-resizable uses inline CSS to handle width and height of a box, and for your issue, I simulate this issue, pay attention to the below screenshot from Google chrome devTools:

enter image description here

The react-resizable-box has an important flag and it overwrites the inline height value so in the view, I have the following behavior:

motion

Your information is not enough so I cannot say directly your issue cause or causes but it is very probable CSS overwriting is the root cause of this issue.

So, inspect the resizable-box on your project and seek to find CSS overwriting.

Update after adding re-produce the issue

Actually, based on my last answer something overwrite your height now in the re-production sandbox, I delete the iframe tag, and everything works well, you pass a height="100%" attribute to your iframe tag and it prevents the change of height. Also, you pass a minConstraints={[300, 500]} to your ResizableBox component, so it could not have a smaller height than 500px.

Related