Bladeren bron

feat: library sidebar design tweaks (#6582)

David Luzar 2 jaren geleden
bovenliggende
commit
fff9d1522a

+ 26 - 5
src/components/LibraryMenu.scss

@@ -1,11 +1,6 @@
 @import "open-color/open-color";
 
 .excalidraw {
-  .library-menu-items-container {
-    height: 100%;
-    width: 100%;
-  }
-
   .layer-ui__library {
     display: flex;
     flex-direction: column;
@@ -70,6 +65,16 @@
     align-items: center;
     justify-content: center;
     gap: 0.625rem;
+    position: relative;
+
+    &--at-bottom::before {
+      content: "";
+      width: calc(100% - 1.5rem);
+      height: 1px;
+      position: absolute;
+      top: -1px;
+      background: var(--sidebar-border-color);
+    }
   }
 
   .library-menu-browse-button {
@@ -126,4 +131,20 @@
       padding: 0.25rem 0.5rem;
     }
   }
+
+  .layer-ui__library .library-menu-dropdown-container {
+    position: relative;
+
+    &--in-heading {
+      padding: 0;
+      position: absolute;
+      top: 1rem;
+      right: 0.75rem;
+      z-index: 1;
+
+      .dropdown-menu {
+        top: 100%;
+      }
+    }
+  }
 }

+ 1 - 2
src/components/LibraryMenu.tsx

@@ -121,12 +121,11 @@ export const LibraryMenuContent = ({
       />
       {showBtn && (
         <LibraryMenuControlButtons
+          className="library-menu-control-buttons--at-bottom"
           style={{ padding: "16px 12px 0 12px" }}
           id={id}
           libraryReturnUrl={libraryReturnUrl}
           theme={appState.theme}
-          selectedItems={selectedItems}
-          onSelectItems={onSelectItems}
         />
       )}
     </LibraryMenuWrapper>

+ 11 - 11
src/components/LibraryMenuControlButtons.tsx

@@ -1,33 +1,33 @@
-import { LibraryItem, ExcalidrawProps, UIAppState } from "../types";
+import { ExcalidrawProps, UIAppState } from "../types";
 import LibraryMenuBrowseButton from "./LibraryMenuBrowseButton";
-import { LibraryDropdownMenu } from "./LibraryMenuHeaderContent";
+import clsx from "clsx";
 
 export const LibraryMenuControlButtons = ({
-  selectedItems,
-  onSelectItems,
   libraryReturnUrl,
   theme,
   id,
   style,
+  children,
+  className,
 }: {
-  selectedItems: LibraryItem["id"][];
-  onSelectItems: (id: LibraryItem["id"][]) => void;
   libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"];
   theme: UIAppState["theme"];
   id: string;
   style: React.CSSProperties;
+  children?: React.ReactNode;
+  className?: string;
 }) => {
   return (
-    <div className="library-menu-control-buttons" style={style}>
+    <div
+      className={clsx("library-menu-control-buttons", className)}
+      style={style}
+    >
       <LibraryMenuBrowseButton
         id={id}
         libraryReturnUrl={libraryReturnUrl}
         theme={theme}
       />
-      <LibraryDropdownMenu
-        selectedItems={selectedItems}
-        onSelectItems={onSelectItems}
-      />
+      {children}
     </div>
   );
 };

+ 7 - 1
src/components/LibraryMenuHeaderContent.tsx

@@ -23,6 +23,7 @@ import { Dialog } from "./Dialog";
 import DropdownMenu from "./dropdownMenu/DropdownMenu";
 import { isLibraryMenuOpenAtom } from "./LibraryMenu";
 import { useUIAppState } from "../context/ui-appState";
+import clsx from "clsx";
 
 const getSelectedItems = (
   libraryItems: LibraryItems,
@@ -37,6 +38,7 @@ export const LibraryDropdownMenuButton: React.FC<{
   resetLibrary: () => void;
   onSelectItems: (items: LibraryItem["id"][]) => void;
   appState: UIAppState;
+  className?: string;
 }> = ({
   setAppState,
   selectedItems,
@@ -45,6 +47,7 @@ export const LibraryDropdownMenuButton: React.FC<{
   resetLibrary,
   onSelectItems,
   appState,
+  className,
 }) => {
   const [libraryItemsData] = useAtom(libraryItemsAtom, jotaiScope);
   const [isLibraryMenuOpen, setIsLibraryMenuOpen] = useAtom(
@@ -236,7 +239,7 @@ export const LibraryDropdownMenuButton: React.FC<{
   };
 
   return (
-    <div style={{ position: "relative" }}>
+    <div className={clsx("library-menu-dropdown-container", className)}>
       {renderLibraryMenu()}
       {selectedItems.length > 0 && (
         <div className="library-actions-counter">{selectedItems.length}</div>
@@ -270,9 +273,11 @@ export const LibraryDropdownMenuButton: React.FC<{
 export const LibraryDropdownMenu = ({
   selectedItems,
   onSelectItems,
+  className,
 }: {
   selectedItems: LibraryItem["id"][];
   onSelectItems: (id: LibraryItem["id"][]) => void;
+  className?: string;
 }) => {
   const { library } = useApp();
   const appState = useUIAppState();
@@ -308,6 +313,7 @@ export const LibraryDropdownMenu = ({
         removeFromLibrary(libraryItemsData.libraryItems)
       }
       resetLibrary={resetLibrary}
+      className={className}
     />
   );
 };

+ 16 - 1
src/components/LibraryMenuItems.scss

@@ -26,6 +26,7 @@
   }
 
   .library-menu-items-container {
+    width: 100%;
     display: flex;
     flex-grow: 1;
     flex-shrink: 1;
@@ -35,10 +36,14 @@
     height: 100%;
     justify-content: center;
     margin: 0;
-    border-bottom: 1px solid var(--sidebar-border-color);
 
     position: relative;
 
+    & > div {
+      padding-left: 0.75rem;
+      padding-right: 0.75rem;
+    }
+
     &__row {
       display: grid;
       grid-template-columns: repeat(4, 1fr);
@@ -59,6 +64,9 @@
       font-size: 1.125rem;
       font-weight: bold;
       margin-bottom: 0.75rem;
+      width: 100%;
+      padding-right: 4rem; // due to dropdown button
+      box-sizing: border-box;
 
       &--excal {
         margin-top: 2rem;
@@ -75,4 +83,11 @@
       color: var(--text-primary-color);
     }
   }
+
+  .library-menu-items-private-library-container {
+    // so that when you toggle between pending item and no items, there's
+    // no layout shift (this is hardcoded and works only with ENG locale)
+    min-height: 3.75rem;
+    width: 100%;
+  }
 }

+ 55 - 41
src/components/LibraryMenuItems.tsx

@@ -15,6 +15,7 @@ import { MIME_TYPES } from "../constants";
 import Spinner from "./Spinner";
 import { duplicateElements } from "../element/newElement";
 import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons";
+import { LibraryDropdownMenu } from "./LibraryMenuHeaderContent";
 
 import "./LibraryMenuItems.scss";
 
@@ -207,6 +208,11 @@ const LibraryMenuItems = ({
 
   const showBtn = !libraryItems.length && !pendingElements.length;
 
+  const isLibraryEmpty =
+    !pendingElements.length &&
+    !unpublishedItems.length &&
+    !publishedItems.length;
+
   return (
     <div
       className="library-menu-items-container"
@@ -218,6 +224,13 @@ const LibraryMenuItems = ({
           : { borderBottom: 0 }
       }
     >
+      {!isLibraryEmpty && (
+        <LibraryDropdownMenu
+          selectedItems={selectedItems}
+          onSelectItems={onSelectItems}
+          className="library-menu-dropdown-container--in-heading"
+        />
+      )}
       <Stack.Col
         className="library-menu-items-container__items"
         align="start"
@@ -228,47 +241,45 @@ const LibraryMenuItems = ({
         }}
       >
         <>
-          <div>
-            {(pendingElements.length > 0 ||
-              unpublishedItems.length > 0 ||
-              publishedItems.length > 0) && (
-              <div className="library-menu-items-container__header">
-                {t("labels.personalLib")}
-              </div>
-            )}
-            {isLoading && (
-              <div
-                style={{
-                  position: "absolute",
-                  top: "var(--container-padding-y)",
-                  right: "var(--container-padding-x)",
-                  transform: "translateY(50%)",
-                }}
-              >
-                <Spinner />
+          {!isLibraryEmpty && (
+            <div className="library-menu-items-container__header">
+              {t("labels.personalLib")}
+            </div>
+          )}
+          {isLoading && (
+            <div
+              style={{
+                position: "absolute",
+                top: "var(--container-padding-y)",
+                right: "var(--container-padding-x)",
+                transform: "translateY(50%)",
+              }}
+            >
+              <Spinner />
+            </div>
+          )}
+          <div className="library-menu-items-private-library-container">
+            {!pendingElements.length && !unpublishedItems.length ? (
+              <div className="library-menu-items__no-items">
+                <div className="library-menu-items__no-items__label">
+                  {t("library.noItems")}
+                </div>
+                <div className="library-menu-items__no-items__hint">
+                  {publishedItems.length > 0
+                    ? t("library.hint_emptyPrivateLibrary")
+                    : t("library.hint_emptyLibrary")}
+                </div>
               </div>
+            ) : (
+              renderLibrarySection([
+                // append pending library item
+                ...(pendingElements.length
+                  ? [{ id: null, elements: pendingElements }]
+                  : []),
+                ...unpublishedItems,
+              ])
             )}
           </div>
-          {!pendingElements.length && !unpublishedItems.length ? (
-            <div className="library-menu-items__no-items">
-              <div className="library-menu-items__no-items__label">
-                {t("library.noItems")}
-              </div>
-              <div className="library-menu-items__no-items__hint">
-                {publishedItems.length > 0
-                  ? t("library.hint_emptyPrivateLibrary")
-                  : t("library.hint_emptyLibrary")}
-              </div>
-            </div>
-          ) : (
-            renderLibrarySection([
-              // append pending library item
-              ...(pendingElements.length
-                ? [{ id: null, elements: pendingElements }]
-                : []),
-              ...unpublishedItems,
-            ])
-          )}
         </>
 
         <>
@@ -304,9 +315,12 @@ const LibraryMenuItems = ({
             id={id}
             libraryReturnUrl={libraryReturnUrl}
             theme={theme}
-            selectedItems={selectedItems}
-            onSelectItems={onSelectItems}
-          />
+          >
+            <LibraryDropdownMenu
+              selectedItems={selectedItems}
+              onSelectItems={onSelectItems}
+            />
+          </LibraryMenuControlButtons>
         )}
       </Stack.Col>
     </div>

+ 12 - 7
src/components/Sidebar/Sidebar.scss

@@ -46,8 +46,17 @@
     justify-content: space-between;
     align-items: center;
     width: 100%;
-    padding-top: 1rem;
-    padding-bottom: 1rem;
+    padding: 1rem 0.75rem;
+    position: relative;
+
+    &::after {
+      content: "";
+      width: calc(100% - 1.5rem);
+      height: 1px;
+      background: var(--sidebar-border-color);
+      position: absolute;
+      bottom: -1px;
+    }
   }
 
   .sidebar__header__buttons {
@@ -89,7 +98,7 @@
     display: flex;
     flex-direction: column;
     flex: 1 1 auto;
-    padding: 1rem 0.75rem;
+    padding: 1rem 0;
 
     [role="tabpanel"] {
       flex: 1;
@@ -161,9 +170,5 @@
         border: none;
       }
     }
-
-    .sidebar__header {
-      border-bottom: 1px solid var(--sidebar-border-color);
-    }
   }
 }