From e5c97f19639db51a56a81dbf9d998f4c55779c80 Mon Sep 17 00:00:00 2001 From: Antoine Clausse Date: Fri, 13 Dec 2024 12:23:34 +0100 Subject: [PATCH] [web] Add box shadows to scrollable part of sidebar (#22400) * Add box shadows to scrollable part of sidebar * Fix lint * Fix `isAtBottom` boolean on Firefox * Throttle the `scroll` event * Remove wrong and unnecessary comment GitOrigin-RevId: 7bcbb7fc860ab32f44203b3ae9ff37a3fed069a8 --- .../components/sidebar/sidebar-ds-nav.tsx | 123 ++++++++++-------- .../components/sidebar/use-scroll.tsx | 39 ++++++ .../pages/project-list-ds-nav.scss | 23 +++- 3 files changed, 127 insertions(+), 58 deletions(-) create mode 100644 services/web/frontend/js/features/project-list/components/sidebar/use-scroll.tsx diff --git a/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx b/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx index f095b0a02e..9a965dc882 100644 --- a/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx +++ b/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx @@ -1,4 +1,5 @@ import { useState } from 'react' +import classnames from 'classnames' import NewProjectButton from '../new-project-button' import SidebarFilters from './sidebar-filters' import AddAffiliation, { useAddAffiliation } from '../add-affiliation' @@ -14,6 +15,7 @@ import { NavbarDropdownItemData } from '@/features/ui/components/types/navbar' import { useContactUsModal } from '@/shared/hooks/use-contact-us-modal' import { UserProvider } from '@/shared/context/user-context' import { AccountMenuItems } from '@/features/ui/components/bootstrap-5/navbar/account-menu-items' +import { useScrolled } from '@/features/project-list/components/sidebar/use-scroll' function SidebarDsNav() { const { t } = useTranslation() @@ -31,6 +33,7 @@ function SidebarDsNav() { const helpItem = items.find( item => item.text === 'help' ) as NavbarDropdownItemData + const { containerRef, scrolledUp, scrolledDown } = useScrolled() return (
- -
+ +
{showAddAffiliationWidget &&
}
-
- -
-
- {helpItem && ( - setShowHelpDropdown(show)} - > - - -
- -
-
-
- - - -
+
+ > +
+ +
+
+ {helpItem && ( setShowAccountDropdown(show)} + onToggle={show => setShowHelpDropdown(show)} > - +
- +
-
- {contactUsModal} - - )} -
-
- - Digital Science - + )} + {sessionUser && ( + <> + setShowAccountDropdown(show)} + > + + +
+ +
+
+
+ + + +
+ {contactUsModal} + + )} +
+
{ + const containerRef = useRef(null) + const [scrolledUp, setScrolledUp] = useState(false) + const [scrolledDown, setScrolledDown] = useState(false) + + const checkScrollPosition = useRef( + throttle(() => { + const container = containerRef.current + if (!container) { + return + } + setScrolledDown(container.scrollTop > 0) + const isAtBottom = + Math.abs( + // On Firefox, this value happen to be at 1 when scrolled to the bottom + container.scrollHeight - container.clientHeight - container.scrollTop + ) <= 1 + setScrolledUp(!isAtBottom) + }, 80) + ).current + + useEffect(() => { + const container = containerRef.current + if (!container) { + return + } + checkScrollPosition() + container.addEventListener('scroll', checkScrollPosition) + return () => { + checkScrollPosition.cancel() + container.removeEventListener('scroll', checkScrollPosition) + } + }, [checkScrollPosition]) + + return { containerRef, scrolledDown, scrolledUp } +} diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/project-list-ds-nav.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/project-list-ds-nav.scss index d7faf7099a..8dfd20a866 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/project-list-ds-nav.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/project-list-ds-nav.scss @@ -32,13 +32,30 @@ flex: 0 0 15%; max-width: 320px; min-width: 200px; - padding: var(--spacing-08) var(--spacing-08) 0 var(--spacing-05); + padding: var(--spacing-08) 0 0 0; + + .new-project-dropdown { + padding: 0 var(--spacing-08) var(--spacing-05) var(--spacing-05); + + &.show-shadow { + box-shadow: 0 2px 2px rgb(0 0 0 / 10%); + } + } .project-list-sidebar-scroll { flex: 1 1 auto; overflow: auto; - margin: var(--spacing-05) calc(var(--spacing-07) * -1); - padding: var(--spacing-05) var(--spacing-07); + margin: 0 var(--spacing-02) 0 0; + padding: var(--spacing-05) var(--spacing-07) var(--spacing-05) + var(--spacing-05); + } + + .ds-nav-sidebar-lower { + padding: var(--spacing-05) var(--spacing-08) 0 var(--spacing-05); + + &.show-shadow { + box-shadow: 0 -2px 2px rgb(0 0 0 / 10%); + } } .project-list-sidebar-survey-link {