Skip to content

Commit

Permalink
feat(Breadcrumb): Handle overflow with more button for hidden folders…
Browse files Browse the repository at this point in the history
… path
  • Loading branch information
Saifullah-dev committed Sep 14, 2024
1 parent 969af30 commit c522dd3
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 116 deletions.
169 changes: 81 additions & 88 deletions frontend/src/FileManager/BreadCrumb/BreadCrumb.jsx
Original file line number Diff line number Diff line change
@@ -1,128 +1,121 @@
import { useEffect, useRef, useState } from "react";
import { MdHome, MdMoreHoriz, MdOutlineNavigateNext } from "react-icons/md";
import { useFileNavigation } from "../../contexts/FileNavigationContext";
import { useDetectOutsideClick } from "../../hooks/useDetectOutsideClick";
import "./BreadCrumb.scss";

const BreadCrumb = () => {
const [folders, setFolders] = useState([]);
const [hiddenFoldersIndexes, setHiddenFoldersIndexes] = useState([]);
const [hiddenFolders, setHiddenFolders] = useState([]);
const [hiddenFoldersWidth, setHiddenFoldersWidth] = useState([]);
const [showHiddenFolders, setShowHiddenFolders] = useState(false);

const { currentPath, setCurrentPath } = useFileNavigation();
const breadCrumbRef = useRef(null);
const foldersRef = useRef([]);
const moreBtnRef = useRef(null);
const popoverRef = useDetectOutsideClick(() => {
setShowHiddenFolders(false);
});

const [hiddenFolders, setHiddenFolders] = useState([]);
const [hiddenFoldersWidth, setHiddenFoldersWidth] = useState([]);
useEffect(() => {
setFolders(() => {
let path = "";
return currentPath?.split("/").map((item) => {
return {
name: item || "Home",
path: item === "" ? item : (path += `/${item}`),
};
});
});
setHiddenFolders([]);
setHiddenFoldersWidth([]);
}, [currentPath]);

const switchPath = (path) => {
setCurrentPath(path);
};

const getBreadCrumbWidth = () => {
const containerWidth = breadCrumbRef.current.clientWidth;
const containerStyles = getComputedStyle(breadCrumbRef.current);
const paddingLeft = parseFloat(containerStyles.paddingLeft);
const flexGap = parseFloat(containerStyles.gap) * (folders.length - 1);
const moreBtnGap = hiddenFolders.length > 0 ? 1 : 0;
const flexGap = parseFloat(containerStyles.gap) * (folders.length + moreBtnGap);
return containerWidth - (paddingLeft + flexGap);
};

const isBreadCrumbOverflowing = () => {
return breadCrumbRef.current.scrollWidth > breadCrumbRef.current.clientWidth;
};

// Change Hidden Folders on resize
// useEffect(() => {
// if (folders.length > 0) {
// const homeFolderWidth = foldersRef.current[0].clientWidth;
// const availableSpace = getBreadCrumbWidth() - homeFolderWidth;

// setHiddenFoldersIndexes(() => {
// return folders.map((_, index) => {
// if (index === 0) return false;

// const remainingFolders = foldersRef.current.slice(index);
// const remainingFoldersWidth = remainingFolders.reduce((prev, curr) => {
// if (!curr) return prev;
// return prev + curr.clientWidth;
// }, 0);

// if (remainingFoldersWidth > availableSpace) return true;
// else return false;
// });
// });
// }
// }, [folders]);
//

useEffect(() => {
setFolders(currentPath?.split("/"));
setHiddenFolders([]);
setHiddenFoldersWidth([]);
}, [currentPath]);

const switchPath = (index) => {
if (index < folders.length - 1) {
setCurrentPath(() => {
const toSlice = folders.length + hiddenFolders.length - (index + 1 + hiddenFolders.length);
const copyFolders = folders.slice(1);
const switchFolders = ["", ...hiddenFolders, ...copyFolders].slice(0, -toSlice);
foldersRef.current = foldersRef.current.slice(0, -toSlice);
return switchFolders.join("/");
});
}
};

const checkAvailableSpace = () => {
const availableSpace = getBreadCrumbWidth();
const remainingFoldersWidth = foldersRef.current.reduce((prev, curr) => {
if (!curr) return prev;
return prev + curr.clientWidth;
}, 0);
const moreBtnWidth = moreBtnRef.current?.clientWidth || 0;
return availableSpace - (remainingFoldersWidth + moreBtnWidth);
};

return availableSpace - remainingFoldersWidth;
const isBreadCrumbOverflowing = () => {
return breadCrumbRef.current.scrollWidth > breadCrumbRef.current.clientWidth;
};

useEffect(() => {
if (isBreadCrumbOverflowing()) {
const hiddenFolder = folders[1];
setHiddenFoldersWidth((prev) => [...prev, foldersRef.current[1].clientWidth]);
const hiddenFolderWidth = foldersRef.current[1]?.clientWidth;
setHiddenFoldersWidth((prev) => [...prev, hiddenFolderWidth]);
setHiddenFolders((prev) => [...prev, hiddenFolder]);
setFolders((prev) => prev.filter((_, index) => index !== 1));
foldersRef.current = foldersRef.current.filter((_, index) => index !== 1);
} else if (hiddenFolders.length > 0 && checkAvailableSpace() > hiddenFoldersWidth.at(-1)) {
const newFolders = [folders[0], hiddenFolders.at(-1), ...folders.slice(1)];
setFolders(newFolders);
setHiddenFolders((prev) => prev.slice(0, -1));
setHiddenFoldersWidth((prev) => prev.slice(0, -1));
}
}, [isBreadCrumbOverflowing]);

// useEffect(() => {
// if (checkAvailableSpace() >= hiddenFoldersWidth.at(-1) && hiddenFolders.length > 0) {
// setFolders((prev) => {
// const prevFolders = prev.slice(hiddenFolders.length);
// const newFolders = ["", hiddenFolders.at(-1), ...prevFolders];
// return newFolders;
// });
// setHiddenFolders((prev) => prev.slice(0, -1));
// setHiddenFoldersWidth((prev) => prev.slice(0, -1));
// }
// }, [breadCrumbRef.current?.clientWidth, currentPath]);

console.table(folders, "Folders");
console.table(hiddenFolders, "Hidden Folders");
console.table(hiddenFoldersWidth, "Hidden Folders Width");

return (
<div className="breadcrumb" ref={breadCrumbRef}>
{folders.map((folder, index) => (
<span
key={index}
className="folder-name"
onClick={() => switchPath(index)}
ref={(el) => (foldersRef.current[index] = el)}
>
{index === 0 ? (
<>
<MdHome /> Home
</>
) : (
<>
<MdOutlineNavigateNext /> {folder}
</>
)}
</span>
))}
<div className="bread-crumb-container">
<div className="breadcrumb" ref={breadCrumbRef}>
{folders.map((folder, index) => (
<div key={index} style={{ display: "contents" }}>
<span
className="folder-name"
onClick={() => switchPath(folder.path)}
ref={(el) => (foldersRef.current[index] = el)}
>
{index === 0 ? <MdHome /> : <MdOutlineNavigateNext />}
{folder.name}
</span>
{hiddenFolders?.length > 0 && index === 0 && (
<button
className="folder-name folder-name-btn"
onClick={() => setShowHiddenFolders(true)}
ref={moreBtnRef}
title="Show more folders"
>
<MdMoreHoriz size={22} className="hidden-folders" />
</button>
)}
</div>
))}
</div>

{showHiddenFolders && (
<ul ref={popoverRef.ref} className="hidden-folders-container">
{hiddenFolders.map((folder, index) => (
<li
key={index}
onClick={() => {
switchPath(folder.path);
setShowHiddenFolders(false);
}}
>
{folder.name}
</li>
))}
</ul>
)}
</div>
);
};
Expand Down
83 changes: 72 additions & 11 deletions frontend/src/FileManager/BreadCrumb/BreadCrumb.scss
Original file line number Diff line number Diff line change
@@ -1,18 +1,79 @@
@import "../../styles/variables";

.breadcrumb {
height: calc(5.8% - 21px);
display: flex;
gap: 0.5rem;
border-bottom: 1px solid #dddddd;
padding: 10px 0 10PX 15px;
overflow-x: hidden;
.bread-crumb-container {
position: relative;

.breadcrumb {
height: calc(5.8% - 21px);
display: flex;
gap: 0.5rem;
border-bottom: 1px solid #dddddd;
padding: 10px 0 10PX 15px;
overflow-x: hidden;

&::-webkit-scrollbar {
height: 3px;
}

&::-webkit-scrollbar-thumb {
background: $primary-color !important;
}

.folder-name {
display: flex;
align-items: center;
gap: 0.25rem;
font-weight: 500;
min-width: fit-content;

&:hover {
cursor: pointer;
color: $secondary-color;
}
}

.hidden-folders {
padding: 0 4px;
}

.folder-name-btn {
background-color: transparent;
border: none;
padding: 0;

&:hover,
&:focus {
cursor: pointer;
color: $primary-color;
background-color: #dddcdc;
border-radius: 5px;
}
}

&::-webkit-scrollbar {
height: 3px;
}
}

.hidden-folders-container {
position: absolute;
margin: 0;
z-index: 2;
background-color: rgb(99, 99, 99);
color: white;
padding: 4px;
border-radius: 5px;
font-size: .9em;
left: 3rem;
display: flex;
flex-direction: column;
gap: 5px;

li {
padding: 5px 10px;
border-radius: 4px;

&::-webkit-scrollbar-thumb {
background: $primary-color !important;
&:hover {
cursor: pointer;
background-color: rgb(117, 117, 117);
}
}
}
13 changes: 0 additions & 13 deletions frontend/src/FileManager/FileManager.scss
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,6 @@ svg {
padding-left: 0px;
border-bottom-right-radius: 8px;
}

.folder-name {
display: flex;
align-items: center;
gap: 0.25rem;
font-weight: 500;
min-width: fit-content;

&:hover {
cursor: pointer;
color: $secondary-color;
}
}
}
}

Expand Down
10 changes: 6 additions & 4 deletions frontend/src/FileManager/Toolbar/Toolbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
display: flex;
justify-content: space-between;

> div {
>div {
display: flex;
}

Expand Down Expand Up @@ -39,7 +39,7 @@
display: flex;
justify-content: space-between;

> div {
>div {
display: flex;
position: relative;
}
Expand All @@ -57,6 +57,7 @@
margin: 0;
border: 1px solid #c4c4c4;
border-radius: 5px;

ul {
list-style: none;
padding-left: 0;
Expand Down Expand Up @@ -113,10 +114,11 @@
}

.icon-only {
padding: 8px !important;
padding: 0 8px !important;

&:focus {
background-color: rgb(0 0 0 / 12%);
border-radius: 3px;
}
}

Expand All @@ -126,4 +128,4 @@
width: 1px;
margin: 0 5px;
}
}
}

0 comments on commit c522dd3

Please sign in to comment.