Yuki Takei 2 лет назад
Родитель
Сommit
93b6bdab83

+ 12 - 15
apps/app/src/components/Sidebar/Sidebar.module.scss

@@ -6,24 +6,22 @@
 
 
 .grw-sidebar :global {
 .grw-sidebar :global {
   top: 0;
   top: 0;
-  border-right : 1px solid var(--bs-border-color);
 
 
-  .grw-sidebar-inner {
-    border-top : 1px solid var(--bs-border-color);
+  .sidebar-contents-container {
+    backdrop-filter: blur(20px);
   }
   }
+}
 
 
+
+// TODO: commonize reload button style
+.grw-sidebar :global {
   .grw-sidebar-content-header {
   .grw-sidebar-content-header {
     .grw-btn-reload {
     .grw-btn-reload {
       font-size: 18px;
       font-size: 18px;
     }
     }
   }
   }
-
-  .sidebar-contents-container {
-    backdrop-filter: blur(20px);
-  }
 }
 }
 
 
-
 // Dock Mode
 // Dock Mode
 .grw-sidebar {
 .grw-sidebar {
   &:global {
   &:global {
@@ -45,13 +43,12 @@
         border-width : 1px 1px 1px 0;
         border-width : 1px 1px 1px 0;
       }
       }
 
 
-      &.open {
-        .sidebar-contents-container {
-          position: absolute;
-          left: var.$grw-sidebar-nav-width;
-          min-height: 50vh;
-          max-height: calc(100vh - var.$grw-sidebar-nav-width * 2);
-        }
+      // open
+      .sidebar-contents-container.open {
+        position: absolute;
+        left: var.$grw-sidebar-nav-width;
+        min-height: 50vh;
+        max-height: calc(100vh - var.$grw-sidebar-nav-width * 2);
       }
       }
     }
     }
   }
   }

+ 90 - 35
apps/app/src/components/Sidebar/Sidebar.tsx

@@ -1,4 +1,5 @@
 import React, {
 import React, {
+  type FC,
   memo, useCallback, useEffect, useState,
   memo, useCallback, useEffect, useState,
 } from 'react';
 } from 'react';
 
 
@@ -14,7 +15,7 @@ import {
 
 
 import { ResizableArea } from './ResizableArea/ResizableArea';
 import { ResizableArea } from './ResizableArea/ResizableArea';
 import { SidebarHead } from './SidebarHead';
 import { SidebarHead } from './SidebarHead';
-import { SidebarNav } from './SidebarNav';
+import { SidebarNav, type SidebarNavProps } from './SidebarNav';
 
 
 import styles from './Sidebar.module.scss';
 import styles from './Sidebar.module.scss';
 
 
@@ -26,7 +27,13 @@ const resizableAreaMinWidth = 348;
 const resizableAreaCollapsedWidth = 48;
 const resizableAreaCollapsedWidth = 48;
 
 
 
 
-export const SidebarSubstance = memo((): JSX.Element => {
+type ResizabeSidebarProps = {
+  children?: React.ReactNode,
+}
+
+const ResizableSidebar = memo((props: ResizabeSidebarProps): JSX.Element => {
+
+  const { children } = props;
 
 
   const { data: isDrawerMode } = useDrawerMode();
   const { data: isDrawerMode } = useDrawerMode();
   const { data: currentProductNavWidth, mutate: mutateProductNavWidth } = useCurrentProductNavWidth();
   const { data: currentProductNavWidth, mutate: mutateProductNavWidth } = useCurrentProductNavWidth();
@@ -69,25 +76,6 @@ export const SidebarSubstance = memo((): JSX.Element => {
     scheduleToPut({ preferCollapsedModeByUser: true });
     scheduleToPut({ preferCollapsedModeByUser: true });
   }, [mutateCollapsedContentsOpened, mutateCollapsedMode]);
   }, [mutateCollapsedContentsOpened, mutateCollapsedMode]);
 
 
-  // open menu when collapsed mode
-  const primaryItemHoverHandler = useCallback(() => {
-    // reject other than collapsed mode
-    if (!isCollapsedMode) {
-      return;
-    }
-
-    mutateCollapsedContentsOpened(true);
-  }, [isCollapsedMode, mutateCollapsedContentsOpened]);
-
-  // close menu when collapsed mode
-  const mouseLeaveHandler = useCallback(() => {
-    // reject other than collapsed mode
-    if (!isCollapsedMode) {
-      return;
-    }
-
-    mutateCollapsedContentsOpened(false);
-  }, [isCollapsedMode, mutateCollapsedContentsOpened]);
 
 
   useEffect(() => {
   useEffect(() => {
     toggleDrawerMode(isDrawerMode);
     toggleDrawerMode(isDrawerMode);
@@ -108,7 +96,6 @@ export const SidebarSubstance = memo((): JSX.Element => {
   }, [currentProductNavWidth, isCollapsedMode, isDrawerMode]);
   }, [currentProductNavWidth, isCollapsedMode, isDrawerMode]);
 
 
   const disableResizing = isResizeDisabled || isDrawerMode || isCollapsedMode;
   const disableResizing = isResizeDisabled || isDrawerMode || isCollapsedMode;
-  const collapsibleContentsWidth = isCollapsedMode ? currentProductNavWidth : undefined;
 
 
   return (
   return (
     <ResizableArea
     <ResizableArea
@@ -120,24 +107,88 @@ export const SidebarSubstance = memo((): JSX.Element => {
       onResizeDone={resizeDoneHandler}
       onResizeDone={resizeDoneHandler}
       onCollapsed={collapsedByResizableAreaHandler}
       onCollapsed={collapsedByResizableAreaHandler}
     >
     >
-      <SidebarHead />
-      <div className="grw-sidebar-inner flex-expand-horiz" onMouseLeave={mouseLeaveHandler}>
-        <SidebarNav onPrimaryItemHover={primaryItemHoverHandler} />
-        <div className="sidebar-contents-container flex-grow-1 overflow-y-auto" style={{ width: collapsibleContentsWidth }}>
-          <SidebarContents />
-        </div>
-      </div>
+      {children}
     </ResizableArea>
     </ResizableArea>
   );
   );
 
 
 });
 });
 
 
+
+type CollapsibleSidebarProps = {
+  Nav: FC<SidebarNavProps>,
+  className?: string,
+  children?: React.ReactNode,
+}
+
+const CollapsibleSidebar = memo((props: CollapsibleSidebarProps): JSX.Element => {
+
+  const { Nav, className, children } = props;
+
+  const { data: currentProductNavWidth } = useCurrentProductNavWidth();
+  const { data: isCollapsedMode } = useCollapsedMode();
+  const { data: isCollapsedContentsOpened, mutate: mutateCollapsedContentsOpened } = useCollapsedContentsOpened();
+
+
+  // open menu when collapsed mode
+  const primaryItemHoverHandler = useCallback(() => {
+    // reject other than collapsed mode
+    if (!isCollapsedMode) {
+      return;
+    }
+
+    mutateCollapsedContentsOpened(true);
+  }, [isCollapsedMode, mutateCollapsedContentsOpened]);
+
+  // close menu when collapsed mode
+  const mouseLeaveHandler = useCallback(() => {
+    // reject other than collapsed mode
+    if (!isCollapsedMode) {
+      return;
+    }
+
+    mutateCollapsedContentsOpened(false);
+  }, [isCollapsedMode, mutateCollapsedContentsOpened]);
+
+  const openClass = `${isCollapsedContentsOpened ? 'open' : ''}`;
+  const collapsibleContentsWidth = isCollapsedMode ? currentProductNavWidth : undefined;
+
+  return (
+    <div className={`flex-expand-horiz ${className}`} onMouseLeave={mouseLeaveHandler}>
+      <Nav onPrimaryItemHover={primaryItemHoverHandler} />
+      <div className={`sidebar-contents-container flex-grow-1 overflow-y-auto ${openClass}`} style={{ width: collapsibleContentsWidth }}>
+        {children}
+      </div>
+    </div>
+  );
+
+});
+
+
+type DrawableSidebarProps = {
+  className?: string,
+  children?: React.ReactNode,
+}
+
+const DrawableSidebar = memo((props: DrawableSidebarProps): JSX.Element => {
+
+  const { className, children } = props;
+
+  const { data: isDrawerOpened } = useDrawerOpened();
+
+  const openClass = `${isDrawerOpened ? 'open' : ''}`;
+
+  return (
+    <div className={`${className} ${openClass}`}>
+      {children}
+    </div>
+  );
+});
+
+
 export const Sidebar = (): JSX.Element => {
 export const Sidebar = (): JSX.Element => {
 
 
   const { data: isDrawerMode } = useDrawerMode();
   const { data: isDrawerMode } = useDrawerMode();
-  const { data: isDrawerOpened } = useDrawerOpened();
   const { data: isCollapsedMode } = useCollapsedMode();
   const { data: isCollapsedMode } = useCollapsedMode();
-  const { data: isCollapsedContentsOpened } = useCollapsedContentsOpened();
 
 
   // css styles
   // css styles
   const grwSidebarClass = styles['grw-sidebar'];
   const grwSidebarClass = styles['grw-sidebar'];
@@ -147,11 +198,15 @@ export const Sidebar = (): JSX.Element => {
     : isCollapsedMode
     : isCollapsedMode
       ? 'grw-sidebar-collapsed'
       ? 'grw-sidebar-collapsed'
       : 'grw-sidebar-dock';
       : 'grw-sidebar-dock';
-  const openClass = `${isDrawerOpened || isCollapsedContentsOpened ? 'open' : ''}`;
 
 
   return (
   return (
-    <div className={`${grwSidebarClass} ${modeClass} ${openClass} vh-100`} data-testid="grw-sidebar">
-      <SidebarSubstance />
-    </div>
+    <DrawableSidebar className={`${grwSidebarClass} ${modeClass} border-end vh-100`} data-testid="grw-sidebar">
+      <ResizableSidebar>
+        <SidebarHead />
+        <CollapsibleSidebar Nav={SidebarNav} className="border-top">
+          <SidebarContents />
+        </CollapsibleSidebar>
+      </ResizableSidebar>
+    </DrawableSidebar>
   );
   );
 };
 };

+ 7 - 6
apps/app/src/components/Sidebar/SidebarHead/SidebarHead.tsx

@@ -24,17 +24,18 @@ export const SidebarHead: FC = memo(() => {
   const popoutClass = isCollapsedMode ? 'popout' : '';
   const popoutClass = isCollapsedMode ? 'popout' : '';
 
 
   return (
   return (
-    <div className={`${styles['grw-sidebar-head']} d-flex w-100`}>
+    <div className={`${styles['grw-sidebar-head']} d-flex justify-content-end w-100`}>
       {/* Brand Logo  */}
       {/* Brand Logo  */}
-      <Link href="/" className={`grw-logo d-block ${popoutClass}`}>
+      {/* <Link href="/" className="grw-logo d-block">
         <SidebarBrandLogo isDefaultLogo={isDefaultLogo} />
         <SidebarBrandLogo isDefaultLogo={isDefaultLogo} />
-      </Link>
-      <div className="flex-grow-1 d-flex align-items-center justify-content-between gap-3 overflow-hidden">
-        <div className={`grw-app-title text-truncate ${popoutClass}`}>
+      </Link> */}
+      {/* <div className="flex-grow-1 d-flex align-items-center justify-content-between gap-3 overflow-hidden">
+        <div className="grw-app-title text-truncate">
           <span className="fs-4">GROWI</span>
           <span className="fs-4">GROWI</span>
         </div>
         </div>
         <ToggleCollapseButton />
         <ToggleCollapseButton />
-      </div>
+      </div> */}
+      <ToggleCollapseButton />
     </div>
     </div>
   );
   );
 
 

+ 2 - 2
apps/app/src/components/Sidebar/SidebarNav/SidebarNav.tsx

@@ -9,11 +9,11 @@ import { SecondaryItems } from './SecondaryItems';
 
 
 import styles from './SidebarNav.module.scss';
 import styles from './SidebarNav.module.scss';
 
 
-type Props = {
+export type SidebarNavProps = {
   onPrimaryItemHover?: (contents: SidebarContentsType) => void,
   onPrimaryItemHover?: (contents: SidebarContentsType) => void,
 }
 }
 
 
-export const SidebarNav = memo((props: Props) => {
+export const SidebarNav = memo((props: SidebarNavProps) => {
   const { onPrimaryItemHover } = props;
   const { onPrimaryItemHover } = props;
 
 
   return (
   return (