Merge pull request #32817 from overleaf/em-account-level-library

[web] Add library page with navbar and sidebar layout

GitOrigin-RevId: b27f8e5dca13bae0cab83a919097c927a025e028
This commit is contained in:
Eric Mc Sween
2026-04-17 10:29:00 -04:00
committed by Copybot
parent 2da03f115f
commit 26820bc327
3 changed files with 163 additions and 136 deletions

View File

@@ -1,43 +1,23 @@
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import classnames from 'classnames'
import { Question, User } from '@phosphor-icons/react'
import NewProjectButton from '../new-project-button'
import SidebarFilters from './sidebar-filters'
import AddAffiliation, { useAddAffiliation } from '../add-affiliation'
import { usePersistedResize } from '@/shared/hooks/use-resize'
import { Dropdown } from 'react-bootstrap'
import getMeta from '@/utils/meta'
import OLTooltip from '@/shared/components/ol/ol-tooltip'
import { NavDropdownMenuItems } from '@/shared/components/navbar/nav-dropdown-from-data'
import { NavbarDropdownItemData } from '@/shared/components/types/navbar'
import { useContactUsModal } from '@/shared/hooks/use-contact-us-modal'
import { UserProvider } from '@/shared/context/user-context'
import { AccountMenuItems } from '@/shared/components/navbar/account-menu-items'
import { useScrolled } from '@/features/project-list/components/sidebar/use-scroll'
import { useSendProjectListMB } from '@/features/project-list/components/project-list-events'
import { SurveyWidgetDsNav } from '@/features/project-list/components/survey-widget-ds-nav'
import { useFeatureFlag } from '@/shared/context/split-test-context'
import { ThemedProjectDashboardNotification } from './themed-project-dashboard-notification'
import { useThemedDashboardIntro } from './use-themed-dashboard-intro'
import { SidebarLowerSection } from '@/shared/components/sidebar/sidebar-lower-section'
function SidebarDsNav() {
const { t } = useTranslation()
const [showAccountDropdown, setShowAccountDropdown] = useState(false)
const [showHelpDropdown, setShowHelpDropdown] = useState(false)
const { showModal: showContactUsModal, modal: contactUsModal } =
useContactUsModal({
autofillProjectUrl: false,
})
const { show: showAddAffiliationWidget } = useAddAffiliation()
const { mousePos, getHandleProps, getTargetProps } = usePersistedResize({
name: 'project-sidebar',
})
const sendMB = useSendProjectListMB()
const { sessionUser, showSubscriptionLink, items } = getMeta('ol-navbar')
const helpItem = items.find(
item => item.text === 'help_and_resources'
) as NavbarDropdownItemData
const { containerRef, scrolledUp, scrolledDown } = useScrolled()
const themedDsNav = useFeatureFlag('themed-project-dashboard')
const {
@@ -80,122 +60,31 @@ function SidebarDsNav() {
scrolledUp && 'show-shadow'
)}
>
<div className="project-list-sidebar-survey-wrapper">
<SurveyWidgetDsNav />
</div>
<nav
className="d-flex flex-row gap-3 mb-2"
aria-label={t('account_help')}
<SidebarLowerSection
showThemeToggle={themedDsNav}
accountRef={targetRef}
onAccountOpen={() => {
if (showingThemedDashboardIntro) {
completeThemedDashboardIntro({
action: 'complete',
event: 'promo-click',
})
}
}}
>
{helpItem && (
<Dropdown
className="ds-nav-icon-dropdown"
onToggle={show => {
setShowHelpDropdown(show)
if (show) {
sendMB('menu-expand', { item: 'help', location: 'sidebar' })
}
}}
role="menu"
>
<Dropdown.Toggle role="menuitem" aria-label={t('help')}>
<OLTooltip
description={t('help')}
id="help-icon"
overlayProps={{
placement: 'top',
}}
hidden={showHelpDropdown}
>
<div>
<Question size={24} />
</div>
</OLTooltip>
</Dropdown.Toggle>
<Dropdown.Menu
as="ul"
role="menu"
align="end"
popperConfig={{
modifiers: [{ name: 'offset', options: { offset: [0, 5] } }],
}}
>
<NavDropdownMenuItems
dropdown={helpItem.dropdown}
showContactUsModal={showContactUsModal}
location="sidebar"
/>
</Dropdown.Menu>
</Dropdown>
<div className="project-list-sidebar-survey-wrapper">
<SurveyWidgetDsNav />
</div>
</SidebarLowerSection>
<UserProvider>
{themedDsNav && (
<ThemedProjectDashboardNotification
target={targetRef.current}
show={showingThemedDashboardIntro}
onDismiss={dismissThemedDashboardIntro}
/>
)}
{sessionUser && (
<>
<Dropdown
className="ds-nav-icon-dropdown"
onToggle={show => {
setShowAccountDropdown(show)
if (show) {
sendMB('menu-expand', {
item: 'account',
location: 'sidebar',
})
if (showingThemedDashboardIntro) {
completeThemedDashboardIntro({
action: 'complete',
event: 'promo-click',
})
}
}
}}
role="menu"
>
<Dropdown.Toggle role="menuitem" aria-label={t('Account')}>
<OLTooltip
description={t('Account')}
id="open-account"
overlayProps={{
placement: 'top',
}}
hidden={showAccountDropdown}
>
<div ref={targetRef}>
<User size={24} />
</div>
</OLTooltip>
</Dropdown.Toggle>
<Dropdown.Menu
as="ul"
role="menu"
align="end"
popperConfig={{
modifiers: [
{ name: 'offset', options: { offset: [-50, 5] } },
],
}}
>
<AccountMenuItems
sessionUser={sessionUser}
showSubscriptionLink={showSubscriptionLink}
showThemeToggle={themedDsNav}
/>
</Dropdown.Menu>
</Dropdown>
<UserProvider>
{themedDsNav && (
<ThemedProjectDashboardNotification
target={targetRef.current}
show={showingThemedDashboardIntro}
onDismiss={dismissThemedDashboardIntro}
/>
)}
{contactUsModal}
</UserProvider>
</>
)}
</nav>
<div className="ds-nav-ds-name" translate="no">
<span>Digital Science</span>
</div>
</UserProvider>
</div>
<div
{...getHandleProps({

View File

@@ -0,0 +1,137 @@
import { type Ref, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Question, User } from '@phosphor-icons/react'
import { Dropdown } from 'react-bootstrap'
import getMeta from '@/utils/meta'
import OLTooltip from '@/shared/components/ol/ol-tooltip'
import { NavDropdownMenuItems } from '@/shared/components/navbar/nav-dropdown-from-data'
import { NavbarDropdownItemData } from '@/shared/components/types/navbar'
import { useContactUsModal } from '@/shared/hooks/use-contact-us-modal'
import { UserProvider } from '@/shared/context/user-context'
import { AccountMenuItems } from '@/shared/components/navbar/account-menu-items'
import { sendMB } from '@/infrastructure/event-tracking'
export function SidebarLowerSection({
showThemeToggle = false,
accountRef,
onAccountOpen,
children,
}: {
showThemeToggle?: boolean
accountRef?: Ref<HTMLDivElement>
onAccountOpen?: () => void
children?: React.ReactNode
}) {
const { t } = useTranslation()
const [showAccountDropdown, setShowAccountDropdown] = useState(false)
const [showHelpDropdown, setShowHelpDropdown] = useState(false)
const { showModal: showContactUsModal, modal: contactUsModal } =
useContactUsModal({
autofillProjectUrl: false,
})
const { sessionUser, showSubscriptionLink, items } = getMeta('ol-navbar')
const helpItem = items.find(
item => item.text === 'help_and_resources'
) as NavbarDropdownItemData
return (
<>
{children}
<nav
className="d-flex flex-row gap-3 mb-2"
aria-label={t('account_help')}
>
{helpItem && (
<Dropdown
className="ds-nav-icon-dropdown"
onToggle={show => {
setShowHelpDropdown(show)
if (show) {
sendMB('menu-expand', { item: 'help', location: 'sidebar' })
}
}}
role="menu"
>
<Dropdown.Toggle role="menuitem" aria-label={t('help')}>
<OLTooltip
description={t('help')}
id="help-icon"
overlayProps={{
placement: 'top',
}}
hidden={showHelpDropdown}
>
<div>
<Question size={24} />
</div>
</OLTooltip>
</Dropdown.Toggle>
<Dropdown.Menu
as="ul"
role="menu"
align="end"
popperConfig={{
modifiers: [{ name: 'offset', options: { offset: [0, 5] } }],
}}
>
<NavDropdownMenuItems
dropdown={helpItem.dropdown}
showContactUsModal={showContactUsModal}
location="sidebar"
/>
</Dropdown.Menu>
</Dropdown>
)}
{sessionUser && (
<Dropdown
className="ds-nav-icon-dropdown"
onToggle={show => {
setShowAccountDropdown(show)
if (show) {
sendMB('menu-expand', {
item: 'account',
location: 'sidebar',
})
onAccountOpen?.()
}
}}
role="menu"
>
<Dropdown.Toggle role="menuitem" aria-label={t('Account')}>
<OLTooltip
description={t('Account')}
id="open-account"
overlayProps={{
placement: 'top',
}}
hidden={showAccountDropdown}
>
<div ref={accountRef}>
<User size={24} />
</div>
</OLTooltip>
</Dropdown.Toggle>
<Dropdown.Menu
as="ul"
role="menu"
align="end"
popperConfig={{
modifiers: [{ name: 'offset', options: { offset: [-50, 5] } }],
}}
>
<AccountMenuItems
sessionUser={sessionUser}
showSubscriptionLink={showSubscriptionLink}
showThemeToggle={showThemeToggle}
/>
</Dropdown.Menu>
</Dropdown>
)}
</nav>
<div className="ds-nav-ds-name" translate="no">
<span>Digital Science</span>
</div>
<UserProvider>{contactUsModal}</UserProvider>
</>
)
}

View File

@@ -312,7 +312,8 @@
}
@include theme('default') {
#project-list-root {
#project-list-root,
#library-root {
.website-redesign-navbar,
.website-redesign .navbar-default {
@include navbar-dark;