From ce1b03cbbc6d92ca2c3bbc50d8a90bdf2fbd29d4 Mon Sep 17 00:00:00 2001 From: 01zulfi <85733202+01zulfi@users.noreply.github.com> Date: Fri, 14 Mar 2025 12:09:20 +0500 Subject: [PATCH] web: fix list pane not expanding (#7758) * web: fix list pane not expanding * when a nav item was clicked, list pane was removed entirely which made it difficult to re-open it, now when nav item is clicked we manually collapse, expand, or reset the list pane * open list pane if 'reveal in list' is called * open list pane if navigated to a different nav item Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> * web: clicking on nav item should not collapse list pane Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> * web: collapse hovered nav pane when notebook/tag item clicked Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> --------- Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com> --- apps/web/src/app.tsx | 26 ++++++++++++-- .../src/components/list-container/index.tsx | 3 ++ .../src/components/navigation-menu/index.tsx | 36 +++++++++++++------ apps/web/src/components/notebook/index.tsx | 6 +++- apps/web/src/components/tag/index.tsx | 2 ++ apps/web/src/stores/app-store.ts | 5 +++ 6 files changed, 64 insertions(+), 14 deletions(-) diff --git a/apps/web/src/app.tsx b/apps/web/src/app.tsx index 34ceaf97a..a9921ff24 100644 --- a/apps/web/src/app.tsx +++ b/apps/web/src/app.tsx @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { useState, Suspense, useEffect, useRef } from "react"; +import { Suspense, useEffect, useRef } from "react"; import { Box, Flex } from "@theme-ui/components"; import { ScopedThemeProvider } from "./components/theme-provider"; import useMobile from "./hooks/use-mobile"; @@ -50,6 +50,8 @@ import { STATUS_BAR_HEIGHT } from "./common/constants"; new WebExtensionRelay(); +const LIST_PANE_SNAP_SIZE = 200; + function App() { const isMobile = useMobile(); const isFocusMode = useStore((store) => store.isFocusMode); @@ -131,15 +133,31 @@ export default App; function DesktopAppContents() { const isFocusMode = useStore((store) => store.isFocusMode); const isListPaneVisible = useStore((store) => store.isListPaneVisible); + const toggleListPane = useStore((store) => store.toggleListPane); const isTablet = useTablet(); // const [isNarrow, setIsNarrow] = useState(isTablet || false); const navPane = useRef(null); + const listPaneSize = useRef(null); useEffect(() => { if (isTablet) navPane.current?.collapse(0); else if (navPane.current?.isCollapsed(0)) navPane.current?.expand(0); }, [isTablet]); + useEffect(() => { + if (isListPaneVisible) { + navPane.current?.expand(1); + return; + } + if ( + listPaneSize.current !== null && + listPaneSize.current < LIST_PANE_SNAP_SIZE + ) { + toggleListPane(); + navPane.current?.reset(1); + } + }, [isListPaneVisible]); + return ( <> { useStore.setState({ isNavPaneCollapsed: sizes[0] <= 70 }); + + listPaneSize.current = sizes[1]; }} > {isFocusMode ? null : ( @@ -173,12 +193,12 @@ function DesktopAppContents() { navPane.current?.reset(0)} /> )} - {!isFocusMode && isListPaneVisible ? ( + {!isFocusMode ? ( diff --git a/apps/web/src/components/list-container/index.tsx b/apps/web/src/components/list-container/index.tsx index 3969fc00d..fd55cf68b 100644 --- a/apps/web/src/components/list-container/index.tsx +++ b/apps/web/src/components/list-container/index.tsx @@ -25,6 +25,7 @@ import { useStore as useSelectionStore, store as selectionStore } from "../../stores/selection-store"; +import { useStore as useAppStore } from "../../stores/app-store"; import GroupHeader from "../group-header"; import { ListItemWrapper, @@ -103,6 +104,7 @@ function ListContainer(props: ListContainerProps) { const toggleSelection = useSelectionStore( (store) => store.toggleSelectionMode ); + const toggleListPane = useAppStore((store) => store.toggleListPane); const listRef = useRef(null); const listContainerRef = useRef(null); @@ -115,6 +117,7 @@ function ListContainer(props: ListContainerProps) { AppEventManager.subscribe( AppEvents.revealItemInList, async (id?: string) => { + toggleListPane(); if (!id || !listRef.current) return; const ids = await items.ids(); diff --git a/apps/web/src/components/navigation-menu/index.tsx b/apps/web/src/components/navigation-menu/index.tsx index 6e1a32be5..14b82abf6 100644 --- a/apps/web/src/components/navigation-menu/index.tsx +++ b/apps/web/src/components/navigation-menu/index.tsx @@ -197,12 +197,17 @@ function NavigationMenu({ onExpand }: { onExpand?: () => void }) { const isFocusMode = useAppStore((store) => store.isFocusMode); const [currentTab, setCurrentTab] = useState<(typeof tabs)[number]>(tabs[0]); const isNavPaneCollapsed = useAppStore((store) => store.isNavPaneCollapsed); - const [expanded, setExpanded] = useState(false); - const isCollapsed = isNavPaneCollapsed && !expanded; + const isCollapsedNavPaneHovered = useAppStore( + (store) => store.isCollapsedNavPaneHovered + ); + const setCollapsedNavPaneHovered = useAppStore( + (store) => store.setCollapsedNavPaneHovered + ); + const isCollapsed = isNavPaneCollapsed && !isCollapsedNavPaneHovered; const mouseHoverTimeout = useRef(0); useEffect(() => { - if (isNavPaneCollapsed) setExpanded(false); + if (isNavPaneCollapsed) setCollapsedNavPaneHovered(false); }, [isNavPaneCollapsed]); return ( @@ -221,7 +226,11 @@ function NavigationMenu({ onExpand }: { onExpand?: () => void }) { borderRight: "1px solid var(--separator)", pt: 1, transition: "width 0.1s ease-in", - width: isNavPaneCollapsed ? (expanded ? 250 : 50) : "100%" + width: isNavPaneCollapsed + ? isCollapsedNavPaneHovered + ? 250 + : 50 + : "100%" }} onMouseEnter={() => { clearTimeout(mouseHoverTimeout.current); @@ -231,7 +240,7 @@ function NavigationMenu({ onExpand }: { onExpand?: () => void }) { if (!isNavPaneCollapsed) return; mouseHoverTimeout.current = setTimeout(() => { if (!isNavPaneCollapsed) return; - setExpanded(false); + setCollapsedNavPaneHovered(false); }, 500) as unknown as number; }} > @@ -239,7 +248,7 @@ function NavigationMenu({ onExpand }: { onExpand?: () => void }) { @@ -322,7 +331,7 @@ function NavigationMenu({ onExpand }: { onExpand?: () => void }) { icon={tab.icon} selected={currentTab.id === tab.id} onClick={() => { - if (isNavPaneCollapsed) setExpanded(true); + if (isNavPaneCollapsed) setCollapsedNavPaneHovered(true); setCurrentTab(tab); }} /> @@ -381,11 +390,11 @@ function NavigationMenu({ onExpand }: { onExpand?: () => void }) { isNavPaneCollapsed && setExpanded(false)} + collapse={() => collapseNavPaneHoveredIfNavPaneCollapsed()} /> isNavPaneCollapsed && setExpanded(false)} + collapse={() => collapseNavPaneHoveredIfNavPaneCollapsed()} /> void }) { /> isNavPaneCollapsed && setExpanded(false)} + collapse={() => collapseNavPaneHoveredIfNavPaneCollapsed()} /> @@ -958,6 +967,13 @@ function navigateToRoute(path: string) { return useSearchStore.getState().resetSearch(); return useAppStore.getState().toggleListPane(); } + useAppStore.getState().toggleListPane(); navigate(path); return true; } + +export function collapseNavPaneHoveredIfNavPaneCollapsed() { + if (useAppStore.getState().isNavPaneCollapsed) { + useAppStore.getState().setCollapsedNavPaneHovered(false); + } +} diff --git a/apps/web/src/components/notebook/index.tsx b/apps/web/src/components/notebook/index.tsx index e1f07044b..e88623993 100644 --- a/apps/web/src/components/notebook/index.tsx +++ b/apps/web/src/components/notebook/index.tsx @@ -43,6 +43,7 @@ import { store as appStore } from "../../stores/app-store"; import { Multiselect } from "../../common/multi-select"; import { strings } from "@notesnook/intl"; import { db } from "../../common/db"; +import { collapseNavPaneHoveredIfNavPaneCollapsed } from "../navigation-menu"; type NotebookProps = { item: NotebookType; @@ -78,7 +79,10 @@ export function Notebook(props: NotebookProps) { isFocused={isOpened} isCompact item={item} - onClick={() => navigate(`/notebooks/${item.id}`)} + onClick={() => { + navigate(`/notebooks/${item.id}`); + collapseNavPaneHoveredIfNavPaneCollapsed(); + }} onDragEnter={(e) => { if (!isDragEntering(e)) return; e.currentTarget.focus(); diff --git a/apps/web/src/components/tag/index.tsx b/apps/web/src/components/tag/index.tsx index 2e8612981..735add731 100644 --- a/apps/web/src/components/tag/index.tsx +++ b/apps/web/src/components/tag/index.tsx @@ -31,6 +31,7 @@ import { useStore as useSelectionStore } from "../../stores/selection-store"; import { useStore as useNoteStore } from "../../stores/note-store"; import { Multiselect } from "../../common/multi-select"; import { strings } from "@notesnook/intl"; +import { collapseNavPaneHoveredIfNavPaneCollapsed } from "../navigation-menu"; type TagProps = { item: TagType; totalNotes: number }; function Tag(props: TagProps) { @@ -87,6 +88,7 @@ function Tag(props: TagProps) { menuItems={tagMenuItems} onClick={() => { navigate(`/tags/${id}`); + collapseNavPaneHoveredIfNavPaneCollapsed(); }} onDragEnter={(e) => { e?.currentTarget.focus(); diff --git a/apps/web/src/stores/app-store.ts b/apps/web/src/stores/app-store.ts index 063bf4308..a84a0c2f8 100644 --- a/apps/web/src/stores/app-store.ts +++ b/apps/web/src/stores/app-store.ts @@ -67,6 +67,7 @@ class AppStore extends BaseStore { isFocusMode = false; isListPaneVisible = true; isNavPaneCollapsed = false; + isCollapsedNavPaneHovered = false; isVaultCreated = false; isAutoSyncEnabled = Config.get("autoSyncEnabled", true); isSyncEnabled = Config.get("syncEnabled", true); @@ -171,6 +172,10 @@ class AppStore extends BaseStore { ); }; + setCollapsedNavPaneHovered = (state: boolean) => { + this.set({ isCollapsedNavPaneHovered: state }); + }; + refresh = async () => { logger.measure("refreshing app");