added animation
This commit is contained in:
@@ -9,22 +9,27 @@ import CreateFolderIcon from "../../icons/CreateFolderIcon";
|
||||
import FolderUploadIcon from "../../icons/FolderUploadIcon";
|
||||
import Swal from "sweetalert2";
|
||||
import { useFolders } from "../../hooks/folders";
|
||||
import classNames from "classnames";
|
||||
|
||||
interface AddNewDropdownProps {
|
||||
closeDropdown: () => void;
|
||||
isDropdownOpen: boolean;
|
||||
}
|
||||
|
||||
const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
const AddNewDropdown: React.FC<AddNewDropdownProps> = ({
|
||||
closeDropdown,
|
||||
isDropdownOpen,
|
||||
}) => {
|
||||
const params = useParams();
|
||||
const { refetch: refetchFolders } = useFolders(false);
|
||||
const [supportsWebkitDirectory, setSupportsWebkitDirectory] = useState(false);
|
||||
const { wrapperRef } = useClickOutOfBounds(props.closeDropdown);
|
||||
const { wrapperRef } = useClickOutOfBounds(closeDropdown, true);
|
||||
const uploadRef: RefObject<HTMLInputElement> = useRef(null);
|
||||
const uploadFolderRef: RefObject<HTMLInputElement> = useRef(null);
|
||||
const { uploadFiles, uploadFolder } = useUploader();
|
||||
|
||||
const createFolder = async () => {
|
||||
props.closeDropdown();
|
||||
closeDropdown();
|
||||
const folderName = await showCreateFolderPopup();
|
||||
|
||||
if (folderName === undefined || folderName === null) {
|
||||
@@ -37,7 +42,7 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
|
||||
const handleUpload = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
props.closeDropdown();
|
||||
closeDropdown();
|
||||
|
||||
const files = uploadRef.current?.files;
|
||||
if (!files) return;
|
||||
@@ -56,7 +61,7 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
|
||||
const handleFolderUpload = (e: React.FormEvent<HTMLInputElement>) => {
|
||||
e.preventDefault();
|
||||
props.closeDropdown();
|
||||
closeDropdown();
|
||||
|
||||
const items = uploadFolderRef.current?.files;
|
||||
|
||||
@@ -101,6 +106,7 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
<div
|
||||
ref={wrapperRef}
|
||||
className="absolute bottom-0 top-full w-full text-gray-500"
|
||||
id="add-new-dropdown"
|
||||
>
|
||||
<input
|
||||
className="hidden"
|
||||
@@ -117,7 +123,12 @@ const AddNewDropdown: React.FC<AddNewDropdownProps> = (props) => {
|
||||
webkitdirectory="true"
|
||||
onChange={handleFolderUpload}
|
||||
/>
|
||||
<ul className="rounded-sm overflow-hidden shadow-lg">
|
||||
<ul
|
||||
className={classNames("rounded-sm overflow-hidden shadow-lg animate", {
|
||||
"h-0": !isDropdownOpen,
|
||||
"h-[132px]": isDropdownOpen,
|
||||
})}
|
||||
>
|
||||
<li>
|
||||
<div>
|
||||
<a
|
||||
|
||||
@@ -26,13 +26,13 @@ const Header = () => {
|
||||
id="header"
|
||||
className="select-none border-b fixed top-0 left-0 w-full bg-white z-10"
|
||||
>
|
||||
<div className="px-6 flex justify-between min-h-16 items-center py-3.5">
|
||||
<div className="px-6 flex justify-between items-center py-3">
|
||||
<div className="items-center w-[260px] hidden desktopMode:flex">
|
||||
<a
|
||||
className="inline-flex items-center justify-center cursor-pointer"
|
||||
onClick={() => navigate("/")}
|
||||
>
|
||||
<img className="w-9" src="/images/icon.png" alt="logo" />
|
||||
<img className="w-8" src="/images/icon.png" alt="logo" />
|
||||
</a>
|
||||
</div>
|
||||
{!isSettings && (
|
||||
@@ -62,7 +62,7 @@ const Header = () => {
|
||||
onClick={() => navigate("/settings")}
|
||||
className="cursor-pointer"
|
||||
>
|
||||
<SettingsIconSolid className="w-7 h-7 text-gray-primary" />
|
||||
<SettingsIconSolid className="w-6 h-6 text-gray-primary" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,19 +23,25 @@ const LeftSection = ({
|
||||
const dispatch = useAppDispatch();
|
||||
const navigate = useNavigate();
|
||||
const addNewDisabled = useRef(false);
|
||||
const closeDropdownDisabled = useRef(true);
|
||||
|
||||
const openDropdown = () => {
|
||||
if (addNewDisabled.current) return;
|
||||
addNewDisabled.current = true;
|
||||
closeDropdownDisabled.current = true;
|
||||
setIsDropdownOpen(true);
|
||||
setTimeout(() => (closeDropdownDisabled.current = false), 300);
|
||||
};
|
||||
|
||||
const closeDropdown = () => {
|
||||
const closeDropdown = useCallback(() => {
|
||||
if (closeDropdownDisabled.current) return;
|
||||
addNewDisabled.current = true;
|
||||
closeDropdownDisabled.current = true;
|
||||
setIsDropdownOpen(false);
|
||||
|
||||
// Clicking out of bounds on the add new button will cause it to reopen
|
||||
setTimeout(() => (addNewDisabled.current = false), 300);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const goHome = () => {
|
||||
dispatch(closeDrawer());
|
||||
@@ -123,7 +129,10 @@ const LeftSection = ({
|
||||
</p>
|
||||
<ChevronSolid className="text-white mr-1" />
|
||||
</a>
|
||||
{isDropdownOpen && <AddNewDropdown closeDropdown={closeDropdown} />}
|
||||
<AddNewDropdown
|
||||
closeDropdown={closeDropdown}
|
||||
isDropdownOpen={isDropdownOpen}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ const MainSection = memo(() => {
|
||||
|
||||
{moveModalItemType && <MoverPopup />}
|
||||
|
||||
<div className="flex flex-row dynamic-height w-screen pt-16">
|
||||
<div className="flex flex-row dynamic-height w-screen pt-12">
|
||||
<LeftSection scrollDivRef={scrollDivRef} />
|
||||
|
||||
{!isMedia ? (
|
||||
|
||||
@@ -91,6 +91,11 @@ const SearchBar = memo(() => {
|
||||
resetState();
|
||||
};
|
||||
|
||||
const calculatedHeight =
|
||||
47 *
|
||||
(searchSuggestions?.folderList.length +
|
||||
searchSuggestions?.fileList.length) || 56;
|
||||
|
||||
const onFocus = () => {
|
||||
dispatch(closeDrawer());
|
||||
setShowSuggestions(true);
|
||||
@@ -121,25 +126,32 @@ const SearchBar = memo(() => {
|
||||
/>
|
||||
)}
|
||||
{isLoadingSearchSuggestions && <div className="spinner-small"></div>}
|
||||
{searchText.length === 0 && <SearchIcon className="w-5 h-5 ml-3" />}
|
||||
{searchText.length === 0 && <SearchIcon className="w-4 h-4 ml-3" />}
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
onChange={onChangeSearch}
|
||||
value={searchText}
|
||||
placeholder={searchTextPlaceholder}
|
||||
className="w-full h-10 border border-gray-300 pl-11 pr-4 text-base text-black rounded-md"
|
||||
className="w-full h-8 border border-gray-300 pl-11 pr-4 text-base text-black rounded-md"
|
||||
onFocus={onFocus}
|
||||
id="search-bar"
|
||||
autoComplete="off"
|
||||
/>
|
||||
<div
|
||||
className="absolute left-0 top-10 bg-white shadow-xl rounded-md w-full max-h-[400px] overflow-y-scroll border border-gray-secondary"
|
||||
style={
|
||||
debouncedSearchText.length !== 0 && showSuggestions
|
||||
? { display: "block" }
|
||||
: { display: "none" }
|
||||
}
|
||||
className={classNames(
|
||||
"absolute left-0 top-8 bg-white shadow-xl rounded-md w-full max-h-[400px] overflow-y-scroll animate-movement",
|
||||
{
|
||||
"border border-gray-secondary":
|
||||
showSuggestions && debouncedSearchText.length,
|
||||
}
|
||||
)}
|
||||
style={{
|
||||
height:
|
||||
showSuggestions && debouncedSearchText.length
|
||||
? calculatedHeight
|
||||
: 0,
|
||||
}}
|
||||
>
|
||||
{searchSuggestions?.folderList.length === 0 &&
|
||||
searchSuggestions?.fileList.length === 0 ? (
|
||||
|
||||
+4
-1
@@ -32,7 +32,10 @@ export const useClickOutOfBounds = (
|
||||
// TODO: Remove this any
|
||||
const outOfBoundsClickCheck = useCallback(
|
||||
(e: MouseEvent | TouchEvent) => {
|
||||
if (wrapperRef && !wrapperRef.current?.contains(e.target as Node)) {
|
||||
if (
|
||||
wrapperRef?.current &&
|
||||
!wrapperRef.current.contains(e.target as Node)
|
||||
) {
|
||||
outOfBoundsCallback(e);
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user