diff --git a/packages/shared/src/components/Feed.module.css b/packages/shared/src/components/Feed.module.css index 89c074beb5..186ea669df 100644 --- a/packages/shared/src/components/Feed.module.css +++ b/packages/shared/src/components/Feed.module.css @@ -2,12 +2,16 @@ grid-template-columns: 100%; } .container { - @screen laptopL { + max-width: 100%; + + @screen desktopL { max-width: calc(20rem * var(--num-cards) + var(--feed-gap) * (var(--num-cards) - 1)); } } .cards { - @screen mobileL { + max-width: 100%; + + @screen desktopL { max-width: calc(20rem * var(--num-cards) + var(--feed-gap) * (var(--num-cards) - 1)); } } diff --git a/packages/shared/src/components/Feed.tsx b/packages/shared/src/components/Feed.tsx index 2a583cf955..60a43f51d9 100644 --- a/packages/shared/src/components/Feed.tsx +++ b/packages/shared/src/components/Feed.tsx @@ -179,9 +179,9 @@ export default function Feed({ const currentSettings = useContext(FeedContext); const { user } = useContext(AuthContext); const { isFallback, query: routerQuery } = useRouter(); - const { openNewTab, spaciness, loadedSettings } = useContext(SettingsContext); + const { openNewTab, loadedSettings } = useContext(SettingsContext); const { isListMode } = useFeedLayout(); - const numCards = currentSettings.numCards[spaciness ?? 'eco']; + const numCards = currentSettings.numCards.eco; const isSquadFeed = feedName === OtherFeedPage.Squad; const { shouldUseListFeedLayout } = useFeedLayout(); const trackedFeedFinish = useRef(false); diff --git a/packages/shared/src/components/MainLayout.tsx b/packages/shared/src/components/MainLayout.tsx index 7c130bee0e..20442a4e97 100644 --- a/packages/shared/src/components/MainLayout.tsx +++ b/packages/shared/src/components/MainLayout.tsx @@ -196,14 +196,14 @@ function MainLayoutComponent({ />
{isAuthReady && showSidebar && ( diff --git a/packages/shared/src/components/feeds/FeedContainer.tsx b/packages/shared/src/components/feeds/FeedContainer.tsx index ea3ba62fe4..78387222b9 100644 --- a/packages/shared/src/components/feeds/FeedContainer.tsx +++ b/packages/shared/src/components/feeds/FeedContainer.tsx @@ -69,7 +69,9 @@ const cardListClass = { export const getFeedGapPx = { 'gap-2': 8, 'gap-3': 12, + 'gap-4': 16, 'gap-5': 20, + 'gap-6': 24, 'gap-8': 32, 'gap-12': 48, 'gap-14': 56, @@ -87,7 +89,7 @@ export const gapClass = ({ if (isFeedLayoutList) { return ''; } - return isList ? listGaps[space] ?? 'gap-2' : gridGaps[space] ?? 'gap-8'; + return isList ? listGaps[space] ?? 'gap-2' : gridGaps[space] ?? 'gap-4'; }; const cardClass = ({ @@ -149,7 +151,7 @@ export const FeedContainer = ({ }: FeedContainerProps): ReactElement => { const currentSettings = useContext(FeedContext); const { subject } = useToastNotification(); - const { spaciness, loadedSettings } = useContext(SettingsContext); + const { loadedSettings } = useContext(SettingsContext); const { shouldUseListFeedLayout, isListMode } = useFeedLayout(); const isLaptop = useViewSize(ViewSize.Laptop); const { feedName } = useActiveFeedNameContext(); @@ -157,7 +159,7 @@ export const FeedContainer = ({ feedName, }); const router = useRouter(); - const numCards = currentSettings.numCards[spaciness ?? 'eco']; + const numCards = currentSettings.numCards.eco; const isList = (isHorizontal || isListMode) && !shouldUseListFeedLayout ? false @@ -167,14 +169,14 @@ export const FeedContainer = ({ gapClass({ isList, isFeedLayoutList: shouldUseListFeedLayout, - space: spaciness, + space: 'eco', }) ]; const style = { '--num-cards': isHorizontal && isListMode && numCards >= 2 ? 2 : numCards, '--feed-gap': `${feedGapPx / 16}rem`, } as CSSProperties; - const cardContainerStyle = { ...getStyle(isList, spaciness) }; + const cardContainerStyle = { ...getStyle(isList, 'eco') }; const isFinder = router.pathname === '/search/posts'; const isSearch = showSearch && !isFinder; @@ -322,7 +324,7 @@ export const FeedContainer = ({ gapClass({ isList, isFeedLayoutList: shouldUseListFeedLayout, - space: spaciness, + space: 'eco', }), cardClass({ isList, numberOfCards: numCards, isHorizontal }), )} diff --git a/packages/shared/src/components/feeds/FeedNav.tsx b/packages/shared/src/components/feeds/FeedNav.tsx index 81a480c03d..6096a96bb4 100644 --- a/packages/shared/src/components/feeds/FeedNav.tsx +++ b/packages/shared/src/components/feeds/FeedNav.tsx @@ -1,11 +1,11 @@ import classNames from 'classnames'; import type { ReactElement } from 'react'; -import React, { useMemo, useState, useTransition } from 'react'; +import React, { useMemo } from 'react'; import { useRouter } from 'next/router'; import { Tab, TabContainer } from '../tabs/TabContainer'; import { useActiveFeedNameContext } from '../../contexts'; import useActiveNav from '../../hooks/useActiveNav'; -import { useEventListener, useFeeds, useViewSize, ViewSize } from '../../hooks'; +import { useFeeds, useViewSize, ViewSize } from '../../hooks'; import usePersistentContext from '../../hooks/usePersistentContext'; import { algorithmsList, @@ -31,7 +31,6 @@ import { SharedFeedPage } from '../utilities'; import PlusMobileEntryBanner from '../banners/PlusMobileEntryBanner'; import { TargetType } from '../../lib/log'; import usePlusEntry from '../../hooks/usePlusEntry'; -import { useAlertsContext } from '../../contexts/AlertContext'; enum FeedNavTab { ForYou = 'For you', @@ -52,17 +51,12 @@ const StickyNavIconWrapper = classed( 'sticky flex h-14 pt-1 -translate-y-16 items-center justify-end bg-gradient-to-r from-transparent via-background-default via-40% to-background-default pr-4', ); -const MIN_SCROLL_BEFORE_HIDING = 60; - function FeedNav(): ReactElement { const router = useRouter(); - const [, startTransition] = useTransition(); - const [isHeaderVisible, setIsHeaderVisible] = useState(true); const { feedName } = useActiveFeedNameContext(); const { sortingEnabled } = useSettingsContext(); const { isSortableFeed } = useFeedName({ feedName }); const { home, bookmarks } = useActiveNav(feedName); - const { alerts } = useAlertsContext(); const isMobile = useViewSize(ViewSize.MobileL); const [selectedAlgo, setSelectedAlgo] = usePersistentContext( DEFAULT_ALGORITHM_KEY, @@ -82,8 +76,6 @@ function FeedNav(): ReactElement { isMobile && ((sortingEnabled && isSortableFeed) || feedName === SharedFeedPage.Custom); - const hasOpportunityAlert = !!alerts.opportunityId; - const urlToTab: Record = useMemo(() => { const customFeeds = sortedFeeds.reduce((acc, { node: feed }) => { const isEditingFeed = @@ -127,45 +119,16 @@ function FeedNav(): ReactElement { isCustomDefaultFeed, ]); - const previousScrollY = React.useRef(0); - - useEventListener(globalThis, 'scroll', () => { - // when scrolled down we should hide the header - // when scrolled up, we should bring it back - const { scrollY } = window; - const shouldHeaderBeVisible = scrollY < previousScrollY.current; - - previousScrollY.current = scrollY; - - if (shouldHeaderBeVisible === isHeaderVisible) { - return; - } - - if (!shouldHeaderBeVisible && scrollY < MIN_SCROLL_BEFORE_HIDING) { - return; - } - - startTransition(() => { - setIsHeaderVisible(shouldHeaderBeVisible); - }); - }); const shouldRenderNav = home || (isMobile && bookmarks); if (!shouldRenderNav || router?.pathname?.startsWith('/posts/[id]')) { return null; } - const headerTransitionClasses = - isMobile && hasOpportunityAlert - ? '-translate-y-[7.5rem] duration-[800ms]' - : '-translate-y-26 duration-[800ms]'; - return (
{isMobile && } diff --git a/packages/shared/src/components/layout/MainLayoutHeader.tsx b/packages/shared/src/components/layout/MainLayoutHeader.tsx index ecb3331fe5..3f1885feeb 100644 --- a/packages/shared/src/components/layout/MainLayoutHeader.tsx +++ b/packages/shared/src/components/layout/MainLayoutHeader.tsx @@ -93,7 +93,7 @@ function MainLayoutHeader({ return (
{ const { children } = props; const { isListMode } = useFeedLayout(); - const { spaciness } = useContext(SettingsContext); const { isSearchPageLaptop } = useSearchResultsLayout(); const { @@ -103,7 +101,7 @@ export const SearchResultsLayout = ( gapClass({ isList: true, isFeedLayoutList: false, - space: spaciness, + space: 'eco', }), isListMode ? `flex flex-col` diff --git a/packages/shared/src/components/sidebar/Section.tsx b/packages/shared/src/components/sidebar/Section.tsx index 7a33d1a9b6..17af9dc7e9 100644 --- a/packages/shared/src/components/sidebar/Section.tsx +++ b/packages/shared/src/components/sidebar/Section.tsx @@ -4,12 +4,12 @@ import React, { useRef } from 'react'; import type { ItemInnerProps, SidebarMenuItem } from './common'; import { NavHeader, NavSection } from './common'; import { SidebarItem } from './SidebarItem'; -import { Button, ButtonSize, ButtonVariant } from '../buttons/Button'; -import { ArrowIcon } from '../icons'; +import { ArrowIcon, PlusIcon } from '../icons'; import type { SettingsFlags } from '../../graphql/settings'; import { useSettingsContext } from '../../contexts/SettingsContext'; import { isNullOrUndefined } from '../../lib/func'; import useSidebarRendered from '../../hooks/useSidebarRendered'; +import Link from '../utilities/Link'; export interface SectionCommonProps extends Pick { @@ -24,6 +24,8 @@ interface SectionProps extends SectionCommonProps { items: SidebarMenuItem[]; isItemsButton: boolean; isAlwaysOpenOnMobile?: boolean; + onAdd?: () => void; + addHref?: string; } export function Section({ @@ -36,6 +38,8 @@ export function Section({ className, flag, isAlwaysOpenOnMobile, + onAdd, + addHref, }: SectionProps): ReactElement { const { flags, updateFlag } = useSettingsContext(); const { sidebarRendered } = useSidebarRendered(); @@ -49,30 +53,79 @@ export function Section({ }; return ( - + {title && ( - - {title} - + {addHref && ( + + + + + + )} + {!addHref && onAdd && ( + + )} +
)} - {(isVisible.current || shouldAlwaysBeVisible) && - items.map((item) => ( +
+ {items.map((item) => ( ))} +
); } diff --git a/packages/shared/src/components/sidebar/Sidebar.spec.tsx b/packages/shared/src/components/sidebar/Sidebar.spec.tsx index a79862683d..343671d3f0 100644 --- a/packages/shared/src/components/sidebar/Sidebar.spec.tsx +++ b/packages/shared/src/components/sidebar/Sidebar.spec.tsx @@ -105,7 +105,7 @@ it('should render the sidebar as open by default', async () => { renderComponent(); const section = await screen.findByText('Discover'); expect(section).toBeInTheDocument(); - const sectionTwo = await screen.findByText('Network'); + const sectionTwo = await screen.findByText('Squads'); expect(sectionTwo).toBeInTheDocument(); }); diff --git a/packages/shared/src/components/sidebar/SidebarDesktop.tsx b/packages/shared/src/components/sidebar/SidebarDesktop.tsx index 38851c1850..037c6f5b3f 100644 --- a/packages/shared/src/components/sidebar/SidebarDesktop.tsx +++ b/packages/shared/src/components/sidebar/SidebarDesktop.tsx @@ -57,38 +57,52 @@ export const SidebarDesktop = ({