feat(Upload.Popup): add popup indicator when dropping files

This commit is contained in:
Aminejv 2021-09-28 18:30:09 +01:00
parent f0849b2604
commit e185c76e5f
4 changed files with 132 additions and 9 deletions

View File

@ -50,7 +50,6 @@ const STYLES_APPLICATION_HEADER_BACKGROUND = (theme) => css`
z-index: -1;
background-color: ${theme.system.white};
box-shadow: 0 0 0 1px ${theme.semantic.bgGrayLight};
@supports ((-webkit-backdrop-filter: blur(75px)) or (backdrop-filter: blur(75px))) {
-webkit-backdrop-filter: blur(75px);
backdrop-filter: blur(75px);
@ -61,7 +60,6 @@ const STYLES_APPLICATION_HEADER_BACKGROUND = (theme) => css`
const STYLES_APPLICATION_HEADER = css`
${Styles.HORIZONTAL_CONTAINER_CENTERED};
padding: 14px 24px;
@media (max-width: ${Constants.sizes.mobile}px) {
padding: 16px 16px 12px;
width: 100%;
@ -94,7 +92,6 @@ const STYLES_BACKGROUND = css`
height: 100vh;
background-color: ${Constants.semantic.bgBlurDark};
pointer-events: auto;
@keyframes fade-in {
from {
opacity: 50%;

View File

@ -25,7 +25,7 @@ import DataMeter from "~/components/core/DataMeter";
* UploadModal
* -----------------------------------------------------------------------------------------------*/
const STYLES_MODAL = css`
const STYLES_MODAL = (theme) => css`
z-index: ${Constants.zindex.uploadModal};
top: ${Constants.sizes.header}px;
right: 0;
@ -33,14 +33,15 @@ const STYLES_MODAL = css`
position: fixed;
left: 0;
padding: 24px 24px 32px;
height: calc(100vh - ${Constants.sizes.header}px);
height: calc(100vh - ${theme.sizes.header}px);
overflow-y: auto;
background-color: ${Constants.semantic.bgBlurWhiteOP};
background-color: ${theme.semantic.bgWhite};
@supports ((-webkit-backdrop-filter: blur(75px)) or (backdrop-filter: blur(75px))) {
-webkit-backdrop-filter: blur(75px);
backdrop-filter: blur(75px);
background-color: ${theme.semantic.bgBlurWhiteOP};
}
`;

View File

@ -0,0 +1,126 @@
import * as React from "react";
import * as System from "~/components/system";
import * as Styles from "~/common/styles";
import * as Strings from "~/common/strings";
import * as FileUtilities from "~/common/file-utilities";
import { css } from "@emotion/react";
import { AnimatePresence, motion } from "framer-motion";
import { Show } from "~/components/utility/Show";
import FilePlaceholder from "~/components/core/ObjectPreview/placeholders/File";
import { clamp } from "lodash";
import { useEventListener } from "~/common/hooks";
const STYLES_POPUP = (theme) => css`
${Styles.CONTAINER_CENTERED};
flex-direction: column;
position: fixed;
width: 100%;
height: 100vh;
top: 0px;
left: 0;
background-color: ${theme.semantic.bgWhite};
@supports ((-webkit-backdrop-filter: blur(75px)) or (backdrop-filter: blur(75px))) {
-webkit-backdrop-filter: blur(75px);
backdrop-filter: blur(75px);
background-color: ${theme.semantic.bgBlurWhiteOP};
}
`;
const STYLES_PLACEHOLDER = css`
width: 64px;
height: 80px;
svg {
height: 100%;
width: 100%;
}
`;
export default function Popup() {
const DEFAULT_DROPPING_STATE = {
isDroppingFiles: false,
totalFilesDropped: undefined,
};
const timerRef = React.useRef();
const [{ isDroppingFiles, totalFilesDropped }, setDroppingState] =
React.useState(DEFAULT_DROPPING_STATE);
const handleDragOver = (e) => {
e.preventDefault();
// NOTE(amine): Hack to hide the popup if the user drags files outside of the app
clearTimeout(timerRef.current);
timerRef.current = setTimeout(() => {
setDroppingState(DEFAULT_DROPPING_STATE);
}, 100);
};
const handleDragEnter = async (e) => {
e.preventDefault();
const { files } = await FileUtilities.formatDroppedFiles({
dataTransfer: e.dataTransfer,
});
setDroppingState({ totalFilesDropped: files.length || undefined, isDroppingFiles: true });
};
useEventListener("dragenter", handleDragEnter, []);
useEventListener("dragover", handleDragOver, []);
return (
<AnimatePresence>
{isDroppingFiles ? (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2, ease: "easeInOut" }}
css={STYLES_POPUP}
>
<DroppedFilesPlaceholder totalFilesDropped={totalFilesDropped} />
<div style={{ marginTop: 64 }}>
<System.H3 as="p" style={{ textAlign: "center" }}>
Dropping {totalFilesDropped}{" "}
{totalFilesDropped ? Strings.pluralize("file", totalFilesDropped) : "files"} to save
to Slate
</System.H3>
<Show when={!totalFilesDropped || totalFilesDropped > 200}>
<System.H5 as="p" color="textGrayDark">
(we recommend uploading 200 files at a time)
</System.H5>
</Show>
</div>
</motion.div>
) : null}
</AnimatePresence>
);
}
const DroppedFilesPlaceholder = ({ totalFilesDropped = 3 }) => {
const marginRight = clamp(totalFilesDropped - 1, 0, 2) * 8;
return (
<div style={{ position: "relative", right: marginRight }}>
<div css={STYLES_PLACEHOLDER}>
<FilePlaceholder />
</div>
<Show when={totalFilesDropped >= 2}>
<div
style={{ position: "absolute", top: -15, right: -16, zIndex: -1 }}
css={STYLES_PLACEHOLDER}
>
<FilePlaceholder />
</div>
</Show>
<Show when={totalFilesDropped >= 3}>
<div
style={{ position: "absolute", top: 2 * -15, right: 2 * -16, zIndex: -2 }}
css={STYLES_PLACEHOLDER}
>
<FilePlaceholder />
</div>
</Show>
</div>
);
};

View File

@ -2,17 +2,16 @@ import * as React from "react";
import * as Styles from "~/common/styles";
import * as System from "~/components/system";
import * as Constants from "~/common/constants";
import * as SVG from "~/common/svg";
import * as Events from "~/common/custom-events";
import { useUploadContext } from "~/components/core/Upload/Provider";
import { Show } from "~/components/utility/Show";
import { ModalPortal } from "../ModalPortal";
import { motion } from "framer-motion";
import { css } from "@emotion/react";
import { Provider } from "~/components/core/Upload/Provider";
import UploadModal from "~/components/core/Upload/Modal";
import Popup from "~/components/core/Upload/Popup";
import DataMeter from "~/components/core/DataMeter";
/* -------------------------------------------------------------------------------------------------
@ -87,4 +86,4 @@ const UploadMetrics = () => {
);
};
export { Provider, Root, Trigger };
export { Provider, Root, Popup, Trigger };