React Resizable box

8632 ワード

ResizableBox.tsx
import React, { useCallback, useRef } from "react"
import { Box, Border } from "./styled"

const ResizableBox: React.FC<{}> = props => {
  const { children } = props
  const boxRef = useRef<HTMLDivElement>(null)

  const handleReSize = useCallback(() => {
    const onMouseMove = (event: MouseEvent) => {
      const element = boxRef.current
      if (!element) return
      
      const curWidth = event.pageX - element.getBoundingClientRect().left
      element.style.width = curWidth + "px"
    }

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

    document.addEventListener("mousemove", onMouseMove)
    document.addEventListener("mouseup", onMouseUp)

    return () => {
      document.removeEventListener("mousemove", onMouseMove)
      document.removeEventListener("mouseup", onMouseUp)
    }
  }, [boxRef, minWidth, maxWidth])

  return (
    <>
      <Box ref={boxRef}>
        {children}
      </Box>
      <Border onMouseDown={handleReSize} />
    </>
  )
}

export default ResizableBox
styled.ts
import styled from "styled-components"

export const Box = styled.div`
    width: 200px;
    height: 100%;
    background-color: #eafdff;
  `

export const Border = styled.div`
  position: relative;
  width: 1px;
  height: 100%;
  background-color: #434c69;
  cursor: w-resize;
  user-select: none;

  :hover::after {
    content: "";
    background-color: #588694;
    position: absolute;
    left: 0;
    width: 4px;
    height: 100%;
    transform: translatex(-50%);
  }
`