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>
This commit is contained in:
01zulfi
2025-03-14 12:09:20 +05:00
committed by Abdullah Atta
parent 577e053816
commit ce1b03cbbc
6 changed files with 64 additions and 14 deletions

View File

@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
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<SplitPaneImperativeHandle>(null);
const listPaneSize = useRef<null | number>(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 (
<>
<Flex
@@ -155,6 +173,8 @@ function DesktopAppContents() {
direction="vertical"
onChange={(sizes) => {
useStore.setState({ isNavPaneCollapsed: sizes[0] <= 70 });
listPaneSize.current = sizes[1];
}}
>
{isFocusMode ? null : (
@@ -173,12 +193,12 @@ function DesktopAppContents() {
<NavigationMenu onExpand={() => navPane.current?.reset(0)} />
</Pane>
)}
{!isFocusMode && isListPaneVisible ? (
{!isFocusMode ? (
<Pane
id="list-pane"
initialSize={380}
style={{ flex: 1, display: "flex" }}
snapSize={200}
snapSize={LIST_PANE_SNAP_SIZE}
maxSize={500}
className="list-pane"
>

View File

@@ -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<VirtuosoHandle>(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();

View File

@@ -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 }) {
<Button
variant="secondary"
sx={{ p: 1, px: "small", bg: "transparent", mx: 1 }}
onClick={() => setExpanded(true)}
onClick={() => setCollapsedNavPaneHovered(true)}
>
<HamburgerMenu size={16} color="icon" />
</Button>
@@ -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 }) {
<Flex sx={{ flexDirection: "column", px: 1, gap: [1, 1, "small"] }}>
<Routes
isCollapsed={isCollapsed}
collapse={() => isNavPaneCollapsed && setExpanded(false)}
collapse={() => collapseNavPaneHoveredIfNavPaneCollapsed()}
/>
<Colors
isCollapsed={isCollapsed}
collapse={() => isNavPaneCollapsed && setExpanded(false)}
collapse={() => collapseNavPaneHoveredIfNavPaneCollapsed()}
/>
<Box
bg="separator"
@@ -394,7 +403,7 @@ function NavigationMenu({ onExpand }: { onExpand?: () => void }) {
/>
<Shortcuts
isCollapsed={isCollapsed}
collapse={() => isNavPaneCollapsed && setExpanded(false)}
collapse={() => collapseNavPaneHoveredIfNavPaneCollapsed()}
/>
</Flex>
</FlexScrollContainer>
@@ -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);
}
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -67,6 +67,7 @@ class AppStore extends BaseStore<AppStore> {
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<AppStore> {
);
};
setCollapsedNavPaneHovered = (state: boolean) => {
this.set({ isCollapsedNavPaneHovered: state });
};
refresh = async () => {
logger.measure("refreshing app");