Looking to add a dynamic divider between two columns that can be adjusted in width by moving the mouse left and right?

If you're looking for an example of two columns adjusting their width based on mouse movement, check out this page from W3Schools. I'm trying to implement this feature in my React app, but I'm unsure of how to proceed.

Below is the JSX code snippet:

... return(
<>
    Container fluid>
            <Row>
              <Col xs={3} style={{ backgroundColor: "red" }}>
                Column 1
              </Col> //here Want to create a middle bar between two columns and add functionality like increase and decrease width depending on the mouse left and right move.
              <Col style={{ backgroundColor: "black" }}>column 2</Col>
            </Row>
          </Container>
</>
)

I attempted to achieve this functionality by using the following code:

const admin = () => {
  const [leftColumnWidth, setLeftColumnWidth] = useState(3); 
  const [isResizing, setIsResizing] = useState(false);

  const handleMouseDown = () => {
    setIsResizing(true);
  };

  const handleMouseUp = () => {
    setIsResizing(false);
  };

  const handleMouseMove = (e) => {
    if (!isResizing) return;

    const containerWidth = e.currentTarget.offsetWidth;
    const mouseX = e.clientX;
    const newLeftColumnWidth = Math.min(
      Math.max((mouseX / containerWidth) * 100, 10), 
      90 
    );

    setLeftColumnWidth(newLeftColumnWidth);
  };
  return (
    <>  
        <Container fluid onMouseMove={handleMouseMove} onMouseUp={handleMouseUp}>
        <Row>
          <Col
            xs={leftColumnWidth}
            style={{
              backgroundColor: "red",
              borderRight: "1px solid black",
              height: "100vh",
              overflow: "hidden",
            }}
          >
            1 of 3
            <div
              style={{
                width: "10px",
                cursor: "col-resize",
                position: "absolute",
                right: 0,
                top: 0,
                bottom: 0,
              }}
              onMouseDown={handleMouseDown}
            ></div>
          </Col>
          <Col style={{ backgroundColor: "black", height: "100vh" }}>
            2 of 3 (wider)
          </Col>
        </Row>
      </Container>
    </>  );
};

However, the above code did not produce the desired result. You can view the outcome here.

The solution provided by Khurram Shafique worked, but I would also like to learn how to implement it for sections B and C. Check out my updated code below:

 <div
        ref={containerRef}
        style={{ display: "flex", height: "100vh", width: "100%" }}
      >
        <div
          style={{
            width: `${columnWidth}%`,
            background: "lightgrey",
            overflow: "auto",
          }}
        >
          <div style={{ height: "500px", padding: "16px" }}>Column A</div>
        </div>
        <div
          ref={handleRef}
          onMouseDown={onMouseDown}
          style={{ cursor: "ew-resize", width: "10px", background: "grey" }}
        />
        <div
          style={{
            width: `${100 - columnWidth}%`,
            display: "flex",
            flexDirection: "column",
          }}
        >
          <div
            style={{
              background: "lightblue",
              overflow: "auto",
              flex: "70%",
            }}
          >
            <div style={{ height: "300px", padding: "16px" }}>Section B</div>
          </div>
          <div
            style={{
              background: "lightgreen",
              height: "30%",
              overflow: "auto",
            }}
          >
            Section C
          </div>
        </div>
      </div>

Answer №1

When working in React, which framework do you prefer - Bootstrap, Tailwind, or Material UI? I have provided a generic code snippet below that can be adapted to fit your specific scenario.

import React, { useState, useRef } from "react";

function ResizableColumns() {
  const [columnWidth, setColumnWidth] = useState(50); // Initial width percentage for column A
  const containerRef = useRef(null);
  const handleRef = useRef(null);

  const onMouseDown = () => {
    document.addEventListener("mousemove", onMouseMove);
    document.addEventListener("mouseup", onMouseUp);
  };

  const onMouseMove = (e) => {
    if (!containerRef.current) return;

    // Calculate the percentage width of column A
    const containerRect = containerRef.current.getBoundingClientRect();
    const newWidth = ((e.clientX - containerRect.left) / containerRect.width) * 100;

    // Update the state with the new width, ensuring it remains within bounds
    setColumnWidth(Math.min(100, Math.max(0, newWidth)));
  };

  const onMouseUp = () => {
    document.removeEventListener("mousemove", onMouseMove);
    document.removeEventListener("mouseup", onMouseUp);
  };

  return (
    <div ref={containerRef} style={{ display: "flex", height: "200px", width: "100%" }}>
      <div style={{ width: `${columnWidth}%`, background: "lightgrey", overflow: "hidden" }}>
        Column A
      </div>
      <div
        ref={handleRef}
        onMouseDown={onMouseDown}
        style={{ cursor: "ew-resize", width: "10px", background: "grey" }}
      />
      <div style={{ width: `${100 - columnWidth}%`, background: "lightblue", overflow: "hidden" }}>
        Column B
      </div>
    </div>
  );
}

export default ResizableColumns;

Answer №2

In the Rendering section, you simply need to add rows in columns by dividing the column into two or as many rows as desired.

 return (
    <div ref={containerRef} style={{ display: "flex", height: "200px", width: "100%" }}>
      <div style={{ width: `${columnWidth}%`, background: "lightgrey", overflow: "hidden" }}>
        Column A
      </div>
      <div
        ref={handleRef}
        onMouseDown={onMouseDown}
        style={{ cursor: "ew-resize", width: "10px", background: "grey" }}
      />
      <div style={{ width: `${100 - columnWidth}%`, background: "lightblue", overflow: "hidden", display: "flex", flexDirection: "column" }}>
        <div style={{ flex: 1, background: "pink", overflow: "hidden" }}>
          Row B1
        </div>
        <div style={{ flex: 1, background: "yellow", overflow: "hidden" }}>
          Row B2
        </div>
      </div>
    </div>
  );

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issues with Ajax Requests

The pending requests from the Post need to be completed. I was hoping to record the JSON body of the request that comes in. Everything works fine when using Postman, but for some reason the AJAX requests are not functioning properly. Code snippet for Node ...

What is the best way to extract the value from a resolved Promise?

Currently, I am attempting to read a file uploaded by the user and convert it into a String using two functions. The first function is handleFileInput: handleFileInput(event){ setTimeOut(async()=>{ let abcd= await this.convertFileToString(this.fi ...

TypeScript React Object.assign method return type

I have a unique custom function that utilizes Object.assign to return a specific result. The documentation mentions that this function returns an array, but surprisingly, it can be destructured both as an array and an object. Check out the code snippet be ...

Integrating React with Node.js/Express for Seamless Communication

I have been experimenting with React and Node.js/Express separately. I currently have two separate files: React (built into HTML/JS) file <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script cro ...

Ways to create unique hover effects for images in a filter gallery

I recently downloaded a filter gallery from this link and while everything is working fine, I noticed that the hover effect remains the same for all images. The code snippet responsible for this hover effect looks like this: <div class="portfolio"> ...

Adjusting Size of Picture and Text on Card

I am currently testing out different effects using the materializecss framework. My goal is to adjust the size of the image and content on a card when the user hovers over it, but I'm having trouble figuring it out. .card:hover .card-image { he ...

Creating a scrollable card layout specifically for small screens in HTML

I am looking to implement a horizontal scroll (for small screens only) within my card layout so that all cards are displayed in a single row. Here is an example: For small screens: So far, I have added horizontal scrolling to the container-fluid (card la ...

Combine two CSS effects in succession using Jquery

I am attempting to combine two CSS transition effects together. The first code snippet works well with 'animate': $('.txt').css({'transition': 'transform .5s ease-in-out ', 'transform': 'translate(3 ...

Update the user information quickly

In my Express application, I have implemented several routes and a login function. Each user has a balance associated with their data, which is stored in an 'express-session'. However, when the user refreshes the page, I need the balance to be up ...

Node.js application encounters a challenge with Swagger UI requirement not being met

My Node.js application utilizes Electron v15.3.1 and includes a Swagger UI for OAS file viewing, specifically version 4.6.1. Due to a security vulnerability in the Swagger UI, I need to upgrade it. Initially, I attempted to resolve the issue by running np ...

unable to send updates to groups in socket.io

When a user connects, the system will search for a room with fewer people than the maximum allowed. If such a room is found, the user joins it. If no suitable room is available, the system creates a new one. The room creation process is functioning correct ...

Having trouble with text decoration not working for a link in Material-UI. Any ideas for a solution?

Currently, I am working on a React/Next.js project and incorporating MUI for the design elements. <Link href="/products"> <ListItem disablePadding> <ListItemButton> <ListItemIcon> ...

Refresh Entity with Real-Time Data on Cesium

I have been attempting to showcase an entity moving within Cesium through the use of live/dynamic data. After trying various techniques and consulting past forums, particularly those from 2015-2016, I am still struggling to make it work. Despite my effort ...

Setting the default value for Material UI select widget

Incorporating material ui into my react application has been challenging. Specifically, I am working with the select component and trying to assign initial values to it. Despite attempting to use the useState hook, I have encountered difficulties. The code ...

Combining Ionic 3 with epubJS

Greetings. I've been attempting to access ePub files in my Ionic 3 test app without success. epubjs has been installed via npm. Here is the package.json contents: { "name": "app_name", "author": "Author", "homepage": "http://example.com/", ...

Experience a captivating Bootstrap 4 drop menu animation that emerges from beyond the borders of the page

I have a row that contains two divs, one with col-md-11 and the other with col-md-1. Inside the col-md-1 div, there is a dropdown that I want to animate. I am using animate css for the animation, but the issue is that the slideInRight animation starts from ...

Dealing with multiple parameters within the app.param() function

Currently, I am developing an API using Express.js and facing a challenge in implementing an app.param() function for handling the id parameter in a GET request: app.param('id', (req, res, next, id) => { const envelopeIndex = Number(id); ...

How can I incorporate the Microsoft Clarity script into the head section of NextJS 13 with an app router?

I've been attempting to integrate Microsoft Clarity into my website using NextJS. Despite trying different methods such as next/head and next/script, I'm unable to add the script in the head section. This issue is preventing Clarity from accurate ...

When the document is fully loaded and processed, a script will be executed immediately following

I'm facing an issue with a modal plugin on my website. The plugin is triggered on $(document).ready, but I have another function (innerHTML) that inserts an <a> element 5-10 seconds after the page loads. This causes the modal not to work properl ...

Changing JSON variable letter case to lowercase using C#

Utilizing the JSONPEncoderFactory and JSONPBehavior method has allowed me to incorporate JSONP into WCF seamlessly. Everything is set up correctly and my service successfully returns data without any issues. However, I am faced with the challenge of conve ...