From 2f890fd86b86cc963adb331d97434331be956756 Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Mon, 3 Mar 2025 11:51:45 +0500 Subject: [PATCH] web: fix scrollbar styling in sidebar --- .../src/components/list-container/index.tsx | 23 ++++++++--- .../src/components/scroll-container/index.tsx | 12 +++--- apps/web/src/components/sidebar-scroller.tsx | 41 +++++++++++++++++++ .../src/components/virtualized-tree/index.tsx | 13 ++++-- apps/web/src/views/notebooks.tsx | 24 ++++++++++- apps/web/src/views/tags.tsx | 19 +++++++-- 6 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 apps/web/src/components/sidebar-scroller.tsx diff --git a/apps/web/src/components/list-container/index.tsx b/apps/web/src/components/list-container/index.tsx index bdf691530..3969fc00d 100644 --- a/apps/web/src/components/list-container/index.tsx +++ b/apps/web/src/components/list-container/index.tsx @@ -33,10 +33,11 @@ import { } from "./list-profiles"; import Announcements from "../announcements"; import { ListLoader } from "../loaders/list-loader"; -import ScrollContainer from "../scroll-container"; +import ScrollContainer, { ScrollContainerProps } from "../scroll-container"; import { useKeyboardListNavigation } from "../../hooks/use-keyboard-list-navigation"; import { VirtualizedGrouping, GroupingKey, Item } from "@notesnook/core"; import { + Components, FlatScrollIntoViewLocation, ItemProps, ScrollerProps, @@ -49,8 +50,9 @@ import { AppEventManager, AppEvents } from "../../common/app-events"; export const CustomScrollbarsVirtualList = forwardRef< HTMLDivElement, - ScrollerProps + ScrollerProps & ScrollContainerProps >(function CustomScrollbarsVirtualList(props, ref) { + console.log({ props, ref }); return ( void; }; + Scroller?: Components["Scroller"]; } & SxProp; function ListContainer(props: ListContainerProps) { - const { type, group, items, context, refresh, header, button, compact, sx } = - props; + const { + type, + group, + items, + context, + refresh, + header, + button, + compact, + sx, + Scroller + } = props; const [focusedGroupIndex, setFocusedGroupIndex] = useState(-1); @@ -213,7 +226,7 @@ function ListContainer(props: ListContainerProps) { onBlur={() => setFocusedGroupIndex(-1)} onKeyDown={(e) => onKeyDown(e.nativeEvent)} components={{ - Scroller: CustomScrollbarsVirtualList, + Scroller: Scroller || CustomScrollbarsVirtualList, Item: VirtuosoItem, Header: ListHeader }} diff --git a/apps/web/src/components/scroll-container/index.tsx b/apps/web/src/components/scroll-container/index.tsx index d2b50212d..41b41f1c2 100644 --- a/apps/web/src/components/scroll-container/index.tsx +++ b/apps/web/src/components/scroll-container/index.tsx @@ -21,28 +21,30 @@ import React, { PropsWithChildren, useLayoutEffect } from "react"; import { MacScrollbar, MacScrollbarProps } from "mac-scrollbar"; import "mac-scrollbar/dist/mac-scrollbar.css"; -type ScrollContainerProps = { +export type ScrollContainerProps = { style?: React.CSSProperties; forwardedRef?: (ref: HTMLDivElement | null) => void; -}; +} & MacScrollbarProps; const ScrollContainer = ({ children, forwardedRef, + style, ...props }: PropsWithChildren) => { return ( { forwardedRef && forwardedRef(div as HTMLDivElement); }} style={{ position: "relative", - height: "100%" + height: "100%", + ...style }} - suppressScrollX - minThumbSize={40} > {children} diff --git a/apps/web/src/components/sidebar-scroller.tsx b/apps/web/src/components/sidebar-scroller.tsx new file mode 100644 index 000000000..97fb6ba13 --- /dev/null +++ b/apps/web/src/components/sidebar-scroller.tsx @@ -0,0 +1,41 @@ +/* +This file is part of the Notesnook project (https://notesnook.com/) + +Copyright (C) 2023 Streetwriters (Private) Limited + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +import { forwardRef } from "react"; +import { ScrollerProps } from "react-virtuoso"; +import ScrollContainer from "./scroll-container"; + +export const SidebarScroller = forwardRef( + function CustomScroller(props, ref) { + return ( + ({ + width: 3 + })} + thumbStyle={() => ({ width: 3 })} + suppressScrollX={true} + forwardedRef={(sRef) => { + if (typeof ref === "function") ref(sRef); + else if (ref) ref.current = sRef; + }} + /> + ); + } +); diff --git a/apps/web/src/components/virtualized-tree/index.tsx b/apps/web/src/components/virtualized-tree/index.tsx index cefbe3a5a..5295088ea 100644 --- a/apps/web/src/components/virtualized-tree/index.tsx +++ b/apps/web/src/components/virtualized-tree/index.tsx @@ -19,7 +19,12 @@ along with this program. If not, see . import { useEffect, useImperativeHandle, useRef, useState } from "react"; import { usePersistentState } from "../../hooks/use-persistent-state"; -import { ItemProps, Virtuoso, VirtuosoHandle } from "react-virtuoso"; +import { + Components, + ItemProps, + Virtuoso, + VirtuosoHandle +} from "react-virtuoso"; import { useKeyboardListNavigation } from "../../hooks/use-keyboard-list-navigation"; import { CustomScrollbarsVirtualList, waitForElement } from "../list-container"; @@ -58,6 +63,8 @@ type TreeViewProps = { deselectAll?: () => void; isSelected?: (id: string) => boolean; style?: React.CSSProperties; + + Scroller?: Components["Scroller"]; }; export function VirtualizedTree(props: TreeViewProps) { const { @@ -75,7 +82,7 @@ export function VirtualizedTree(props: TreeViewProps) { deselectAll, bulkSelect, testId, - style + Scroller } = props; const [nodes, setNodes] = useState[]>([]); const [expandedIds, setExpandedIds] = usePersistentState( @@ -205,7 +212,7 @@ export function VirtualizedTree(props: TreeViewProps) { onMouseUp }} components={{ - Scroller: CustomScrollbarsVirtualList, + Scroller: (Scroller as any) || CustomScrollbarsVirtualList, Item: VirtuosoItem, EmptyPlaceholder: Placeholder }} diff --git a/apps/web/src/views/notebooks.tsx b/apps/web/src/views/notebooks.tsx index 5fd75a640..5706eb632 100644 --- a/apps/web/src/views/notebooks.tsx +++ b/apps/web/src/views/notebooks.tsx @@ -19,7 +19,13 @@ along with this program. If not, see . import { Notebook as NotebookType, VirtualizedGrouping } from "@notesnook/core"; import { Box, Flex, Input, Text } from "@theme-ui/components"; -import { useEffect, useLayoutEffect, useRef, useState } from "react"; +import { + forwardRef, + useEffect, + useLayoutEffect, + useRef, + useState +} from "react"; import { db } from "../common/db"; import { store, useStore } from "../stores/notebook-store"; import { useStore as useSelectionStore } from "../stores/selection-store"; @@ -33,6 +39,10 @@ import { import { ListLoader } from "../components/loaders/list-loader"; import { debounce } from "@notesnook/common"; import { strings } from "@notesnook/intl"; +import { CustomScrollbarsVirtualList } from "../components/list-container"; +import { ScrollerProps } from "react-virtuoso"; +import ScrollContainer from "../components/scroll-container"; +import { SidebarScroller } from "../components/sidebar-scroller"; export function Notebooks() { const roots = useStore((store) => store.notebooks); @@ -81,7 +91,16 @@ export function Notebooks() { return ( <> - + )} + Scroller={SidebarScroller} /> store.tags); @@ -39,14 +42,24 @@ function Tags() { if (!items) return ; return ( - + } header={<>} + Scroller={SidebarScroller} />