파일 Drag and Drop 기능을 구현하자!
사용자 경험 개선을 위한 파일 Drag and Drop 기능 추가
velog.io
import React, { useState } from "react";
import styled from "styled-components";
import dndImage1 from "../assets/DnDBox1.svg";
import dndImage2 from "../assets/DnDBox2.svg";
import uploadIcon1 from "../assets/fileUpload1.svg";
import uploadIcon2 from "../assets/fileUpload2.svg";
// 사용자로부터 파일을 입력받는다.
const FileInputForm = ({ selectedFile, setSelectedFile }) => {
  const [dragActive, setDragActive] = useState(false);
  const handleDrag = (event) => {
    event.preventDefault();
    event.stopPropagation();
    if (event.type === "dragenter" || event.type === "dragover") {
      setDragActive(true);
    } else if (event.type === "dragleave") {
      setDragActive(false);
    }
  };
  const handleDrop = (event) => {
    event.preventDefault();
    event.stopPropagation();
    setDragActive(false);
    const files = event.dataTransfer.files;
    if (files && files[0]) {
      setSelectedFile(files[0]);
      handleFileChange({ target: { files } });
    }
  };
  // 파일 입력받기
  const handleFileChange = (event) => {
    setSelectedFile(event.target.files[0]);
  };
  return (
    <>
      <HiddenFileInput type="file" id="fileInput" accept=".xlsx, .xls" onChange={handleFileChange} />
      <CustomFileLabel htmlFor="fileInput">파일 선택</CustomFileLabel>
      <DnDBox
        onDragEnter={handleDrag}
        onDragLeave={handleDrag}
        onDragOver={handleDrag}
        onDrop={handleDrop}
        isDragging={dragActive}
        dragActive={dragActive}
      >
        <DnDIcon src={dragActive ? uploadIcon2 : uploadIcon1} />
        {selectedFile ? (
          <DnDText dragActive={dragActive}>{selectedFile?.name}</DnDText>
        ) : (
          <DnDText dragActive={dragActive}>파일을 이곳에 첨부해 주세요 :)</DnDText>
        )}
      </DnDBox>
    </>
  );
};
// 숨겨진 파일 인풋
const HiddenFileInput = styled.input`
  display: none;
`;
// 파일 선택 버튼 스타일
const CustomFileLabel = styled.label`
  width: 326px;
  height: 53px;
  background-color: #303030;
  color: #ffffff;
  border-radius: 15px;
  font-size: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 68px;
  &:hover {
    opacity: 0.9;
    cursor: pointer;
  }
`;
const DnDBox = styled.div`
  width: 802px;
  height: 130px;
  margin-top: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 15px;
  background-image: url(${(props) => (props.dragActive ? dndImage2 : dndImage1)});
  background-size: cover; /* 이미지가 화면을 덮도록 */
  background-position: center; /* 이미지가 중앙에 위치하도록 */
  background-repeat: no-repeat; /* 이미지가 반복되지 않도록 */
`;
const DnDIcon = styled.img`
  margin-right: 10px;
  color: red;
`;
const DnDText = styled.div`
  font-size: 20px;
  color: ${(props) => (props.dragActive ? "#9BA5FF" : "black")};
`;
export default FileInputForm;'프론트엔드 > CSS' 카테고리의 다른 글
| [CSS] SCSS @extend @mixin 차이점(GPT4.0) (0) | 2024.08.26 | 
|---|---|
| [CSS] 스크롤로 페이지 넘기기(스크롤 스냅) (0) | 2024.08.24 | 
| [CSS3] CSS 포커스 상태 유지시키기 (1) | 2024.07.31 | 
| 체크박스 스타일링 (0) | 2024.05.17 | 
| [CSS] StyledComponents props 전달 방법 (0) | 2024.01.23 |