diff --git a/interface/app/$libraryId/overview/Categories.tsx b/interface/app/$libraryId/overview/Categories.tsx index c65cd885d..ace0bce69 100644 --- a/interface/app/$libraryId/overview/Categories.tsx +++ b/interface/app/$libraryId/overview/Categories.tsx @@ -3,10 +3,13 @@ import clsx from 'clsx'; import { motion } from 'framer-motion'; import { ArrowLeft, ArrowRight } from 'phosphor-react'; import { RefObject, useEffect, useRef, useState } from 'react'; +import Sticky from 'react-sticky-el'; import { useDraggable } from 'react-use-draggable-scroll'; import { Category, useLibraryQuery } from '@sd/client'; +import { tw } from '@sd/ui'; import { useIsDark } from '~/hooks'; import { useLayoutContext } from '../Layout/Context'; +import { usePageLayoutContext } from '../PageLayout/Context'; import CategoryButton from './CategoryButton'; import { IconForCategory } from './data'; @@ -30,9 +33,13 @@ const CategoryList = [ 'Trash' ] as Category[]; +const ArrowButton = tw.div`absolute top-1/2 z-40 flex h-8 w-8 shrink-0 -translate-y-1/2 items-center p-2 cursor-pointer justify-center rounded-full border border-app-line bg-app/50 hover:opacity-95 backdrop-blur-md transition-all duration-200`; + export const Categories = (props: { selected: Category; onSelectedChanged(c: Category): void }) => { const isDark = useIsDark(); + const { ref: pageRef } = usePageLayoutContext(); + const ref = useRef(null); const { events } = useDraggable(ref as React.MutableRefObject); @@ -56,70 +63,74 @@ export const Categories = (props: { selected: Category; onSelectedChanged(c: Cat index === CategoryList.length - 1 && setLastCategoryVisible((prev) => !prev); }; + const maskImage = `linear-gradient(90deg, transparent 0.1%, rgba(0, 0, 0, 1) ${ + scroll > 0 ? '10%' : '0%' + }, rgba(0, 0, 0, 1) ${lastCategoryVisible ? '95%' : '85%'}, transparent 99%)`; + return ( -
-
handleArrowOnClick('right')} - className={clsx( - scroll > 0 - ? 'cursor-pointer bg-app/50 opacity-100 hover:opacity-95' - : 'pointer-events-none', - 'sticky left-[15px] z-40 -ml-4 mt-4 flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-app-line bg-app p-2 opacity-0 backdrop-blur-md transition-all duration-200' - )} - > - + +
+ handleArrowOnClick('right')} + className={clsx('left-3', scroll === 0 && 'pointer-events-none opacity-0')} + > + + + +
+ {categories.data && + CategoryList.map((category, index) => { + const iconString = IconForCategory[category] || 'Document'; + return ( + lastCategoryVisibleHandler(index)} + onViewportLeave={() => lastCategoryVisibleHandler(index)} + viewport={{ + root: ref, + // WARNING: Edge breaks if the values are not postfixed with px or % + margin: '0% -120px 0% 0%' + }} + className={clsx( + 'min-w-fit', + mouseState !== 'dragging' && '!cursor-default' + )} + key={category} + > + props.onSelectedChanged(category)} + /> + + ); + })} +
+ + handleArrowOnClick('left')} + className={clsx( + 'right-3', + lastCategoryVisible && 'pointer-events-none opacity-0' + )} + > + +
-
0 ? '10%' : '0%' - }, rgba(0, 0, 0, 1) ${lastCategoryVisible ? '95%' : '85%'}, transparent 99%)` - }} - > - {categories.data && - CategoryList.map((category, index) => { - const iconString = IconForCategory[category] || 'Document'; - return ( - lastCategoryVisibleHandler(index)} - onViewportLeave={() => lastCategoryVisibleHandler(index)} - viewport={{ - root: ref, - // WARNING: Edge breaks if the values are not postfixed with px or % - margin: '0% -120px 0% 0%' - }} - className={clsx( - 'min-w-fit', - mouseState !== 'dragging' && '!cursor-default' - )} - key={category} - > - props.onSelectedChanged(category)} - /> - - ); - })} -
-
handleArrowOnClick('left')} - className={clsx( - lastCategoryVisible - ? 'pointer-events-none opacity-0 hover:opacity-0' - : 'hover:opacity-95', - 'sticky right-[15px] z-40 mt-4 flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-full border border-app-line bg-app/50 p-2 backdrop-blur-md transition-all duration-200' - )} - > - -
-
+ ); }; diff --git a/interface/app/$libraryId/overview/Statistics.tsx b/interface/app/$libraryId/overview/Statistics.tsx index f3936f42d..48c88eaa3 100644 --- a/interface/app/$libraryId/overview/Statistics.tsx +++ b/interface/app/$libraryId/overview/Statistics.tsx @@ -106,7 +106,7 @@ export default () => { }); mounted = true; return ( -
+
{/* STAT CONTAINER */}
{Object.entries(stats?.data || []).map(([key, value]) => { diff --git a/interface/package.json b/interface/package.json index 23c0a0dd4..6ed9841c4 100644 --- a/interface/package.json +++ b/interface/package.json @@ -58,6 +58,7 @@ "react-router-dom": "6.9.0", "react-scroll-sync": "^0.11.0", "react-selecto": "^1.22.3", + "react-sticky-el": "^2.1.0", "react-use-draggable-scroll": "^0.4.7", "remix-params-helper": "^0.4.10", "rooks": "^5.14.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0ec00c3eb..f1935a700 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,7 +49,7 @@ importers: version: 5.0.4 vite: specifier: ^4.3.9 - version: 4.3.9(@types/node@18.15.1) + version: 4.3.9(less@4.1.3) apps/desktop: dependencies: @@ -563,7 +563,7 @@ importers: version: 5.0.4 vite: specifier: ^4.0.4 - version: 4.3.9(@types/node@18.15.1) + version: 4.3.9(less@4.1.3) vite-plugin-html: specifier: ^3.2.0 version: 3.2.0(vite@4.3.9) @@ -603,7 +603,7 @@ importers: version: 4.8.2 vite: specifier: ^4.0.4 - version: 4.3.9(@types/node@18.15.1) + version: 4.3.9(less@4.1.3) interface: dependencies: @@ -730,6 +730,9 @@ importers: react-selecto: specifier: ^1.22.3 version: 1.22.3 + react-sticky-el: + specifier: ^2.1.0 + version: 2.1.0(react-dom@18.2.0)(react@18.2.0) react-use-draggable-scroll: specifier: ^0.4.7 version: 0.4.7(react@18.2.0) @@ -10600,7 +10603,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.22.1) magic-string: 0.26.7 react-refresh: 0.14.0 - vite: 4.3.9(sass@1.55.0) + vite: 4.3.9(@types/node@18.15.1) transitivePeerDependencies: - supports-color @@ -20946,6 +20949,16 @@ packages: react: 18.2.0 react-is: 18.2.0 + /react-sticky-el@2.1.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-oo+a2GedF4QMfCfm20e9gD+RuuQp/ngvwGMUXAXpST+h4WnmKhuv7x6MQ4X/e3AHiLYgE0zDyJo1Pzo8m51KpA==} + peerDependencies: + react: '>=16.3.0' + react-dom: '>=16.3.0' + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /react-style-singleton@2.2.1(@types/react@18.0.38)(react@18.2.0): resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} engines: {node: '>=10'} @@ -24143,7 +24156,7 @@ packages: dependencies: '@rollup/pluginutils': 4.2.1 '@svgr/core': 6.5.1 - vite: 4.3.9(sass@1.55.0) + vite: 4.3.9(@types/node@18.15.1) transitivePeerDependencies: - supports-color dev: true @@ -24157,7 +24170,7 @@ packages: globrex: 0.1.2 recrawl-sync: 2.2.3 tsconfig-paths: 4.2.0 - vite: 4.3.9(@types/node@18.15.1) + vite: 4.3.9(less@4.1.3) transitivePeerDependencies: - supports-color dev: true @@ -24240,7 +24253,6 @@ packages: rollup: 3.26.0 optionalDependencies: fsevents: 2.3.2 - dev: true /vite@4.3.9(less@4.1.3): resolution: {integrity: sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==}