AuthriX / frontend-react /src /components /FileUploadInput.tsx
Deepfake Authenticator
feat: replace vanilla frontend with React + Vite UI
70348ce
import styled from 'styled-components';
interface FileUploadInputProps {
onFile: (f: File) => void;
}
const StyledWrapper = styled.div`
.container {
--transition: 350ms;
--folder-W: 120px;
--folder-H: 80px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
padding: 10px;
background: linear-gradient(135deg, #4c1d95, #7c3aed);
border-radius: 15px;
box-shadow: 0 15px 30px rgba(88, 28, 135, 0.4);
height: calc(var(--folder-H) * 1.7);
position: relative;
}
.folder {
position: absolute;
top: -20px;
left: calc(50% - 60px);
animation: float 2.5s infinite ease-in-out;
transition: transform var(--transition) ease;
}
.folder:hover {
transform: scale(1.05);
}
.folder .front-side,
.folder .back-side {
position: absolute;
transition: transform var(--transition);
transform-origin: bottom center;
}
.folder .back-side::before,
.folder .back-side::after {
content: "";
display: block;
background-color: #c084fc;
opacity: 0.35;
width: var(--folder-W);
height: var(--folder-H);
position: absolute;
transform-origin: bottom center;
border-radius: 15px;
transition: transform 350ms;
z-index: 0;
}
.container:hover .back-side::before {
transform: rotateX(-5deg) skewX(5deg);
}
.container:hover .back-side::after {
transform: rotateX(-15deg) skewX(12deg);
}
.folder .front-side {
z-index: 1;
}
.container:hover .front-side {
transform: rotateX(-40deg) skewX(15deg);
}
.folder .tip {
background: linear-gradient(135deg, #a855f7, #7c3aed);
width: 80px;
height: 20px;
border-radius: 12px 12px 0 0;
box-shadow: 0 5px 15px rgba(124, 58, 237, 0.5);
position: absolute;
top: -10px;
z-index: 2;
}
.folder .cover {
background: linear-gradient(135deg, #c084fc, #a855f7);
width: var(--folder-W);
height: var(--folder-H);
box-shadow: 0 15px 30px rgba(88, 28, 135, 0.5);
border-radius: 10px;
}
.custom-file-upload {
font-size: 1em;
font-family: 'Space Grotesk', sans-serif;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #ffffff;
text-align: center;
background: rgba(255, 255, 255, 0.12);
border: none;
border-radius: 10px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
cursor: pointer;
transition: background var(--transition) ease;
display: inline-block;
width: 100%;
padding: 10px 35px;
position: relative;
}
.custom-file-upload:hover {
background: rgba(255, 255, 255, 0.22);
}
.custom-file-upload input[type="file"] {
display: none;
}
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-20px); }
100% { transform: translateY(0px); }
}
`;
export default function FileUploadInput({ onFile }: FileUploadInputProps) {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const f = e.target.files?.[0];
if (f && f.type.startsWith('video/')) onFile(f);
};
return (
<StyledWrapper>
<div className="container">
<div className="folder">
<div className="front-side">
<div className="tip" />
<div className="cover" />
</div>
<div className="back-side cover" />
</div>
<label className="custom-file-upload">
<input className="title" type="file" accept="video/*" onChange={handleChange} />
Upload a File
</label>
</div>
</StyledWrapper>
);
}