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");