From db88c93effd220f7a62925203ce3e57b170e3783 Mon Sep 17 00:00:00 2001 From: nitin <142569587+ehconitin@users.noreply.github.com> Date: Thu, 10 Apr 2025 17:35:10 +0530 Subject: [PATCH] Navigation drawer refactor (#11251) closes #11195 closes #11199 ### Context The yellow dots in the Settings Navigation Drawer (used to indicate advanced settings) were being hidden due to ScrollWrapper's overflow handling. This required both a fix for the visibility issue and an improvement to the component structure. ### Changes 1. Keep scrolling logic of the MainNavigationDrawer and SettingsNavigationDrawer in one place, and conditionally apply `` when isSettingsDrawer is true. 2. Fixed Yellow Dots Visibility Added specific padding in NavigationDrawerScrollableContent to accommodate yellow dots: ``` padding-left: ${theme.spacing(5)}; // Space for yellow dots padding-right: ${theme.spacing(8)}; // Space for no-padding scroll ``` This ensures the yellow dots are visible while maintaining proper scroll behavior 3. Improved Component Composition Using proper component composition instead of passing components as props Components are now composed in a more React-idiomatic way: ``` ``` --------- Co-authored-by: Charles Bochet --- .../components/AppNavigationDrawer.tsx | 53 +------ .../components/MainNavigationDrawer.tsx | 32 ++++ .../MainNavigationDrawerFixedItems.tsx | 52 +++++++ .../components/MainNavigationDrawerItems.tsx | 82 ---------- .../MainNavigationDrawerScrollableItems.tsx | 22 +++ .../components/SettingsNavigationDrawer.tsx | 35 +++++ .../SettingsNavigationDrawerItems.tsx | 140 ++++++++---------- .../SignInAppNavigationDrawerMock.tsx | 20 +-- .../layout/page/components/DefaultLayout.tsx | 2 +- .../components/NavigationDrawer.tsx | 40 ++--- .../components/NavigationDrawerBackButton.tsx | 1 + .../NavigationDrawerFixedContent.tsx | 33 +++++ .../NavigationDrawerScrollableContent.tsx | 48 ++++++ .../components/NavigationDrawerSection.tsx | 21 ++- .../__stories__/NavigationDrawer.stories.tsx | 28 ++-- 15 files changed, 342 insertions(+), 267 deletions(-) create mode 100644 packages/twenty-front/src/modules/navigation/components/MainNavigationDrawer.tsx create mode 100644 packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerFixedItems.tsx delete mode 100644 packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx create mode 100644 packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerScrollableItems.tsx create mode 100644 packages/twenty-front/src/modules/navigation/components/SettingsNavigationDrawer.tsx create mode 100644 packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx create mode 100644 packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx diff --git a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx index b93536c42..1b15fbbc1 100644 --- a/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx +++ b/packages/twenty-front/src/modules/navigation/components/AppNavigationDrawer.tsx @@ -1,19 +1,7 @@ -import { useRecoilState, useRecoilValue } from 'recoil'; - -import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; -import { SettingsNavigationDrawerItems } from '@/settings/components/SettingsNavigationDrawerItems'; -import { SupportDropdown } from '@/support/components/SupportDropdown'; -import { - NavigationDrawer, - NavigationDrawerProps, -} from '@/ui/navigation/navigation-drawer/components/NavigationDrawer'; -import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState'; - import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer'; -import { MainNavigationDrawerItems } from '@/navigation/components/MainNavigationDrawerItems'; -import { useLingui } from '@lingui/react/macro'; -import { AdvancedSettingsToggle } from 'twenty-ui/navigation'; +import { MainNavigationDrawer } from '@/navigation/components/MainNavigationDrawer'; +import { SettingsNavigationDrawer } from '@/navigation/components/SettingsNavigationDrawer'; export type AppNavigationDrawerProps = { className?: string; @@ -24,38 +12,9 @@ export const AppNavigationDrawer = ({ }: AppNavigationDrawerProps) => { const isSettingsDrawer = useIsSettingsDrawer(); - const currentWorkspace = useRecoilValue(currentWorkspaceState); - const [isAdvancedModeEnabled, setIsAdvancedModeEnabled] = useRecoilState( - isAdvancedModeEnabledState, - ); - - const { t } = useLingui(); - - const drawerProps: NavigationDrawerProps = isSettingsDrawer - ? { - title: t`Exit Settings`, - children: , - footer: ( - - ), - } - : { - title: currentWorkspace?.displayName ?? '', - children: , - footer: , - }; - - return ( - - {drawerProps.children} - + return isSettingsDrawer ? ( + + ) : ( + ); }; diff --git a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawer.tsx b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawer.tsx new file mode 100644 index 000000000..92f846090 --- /dev/null +++ b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawer.tsx @@ -0,0 +1,32 @@ +import { useRecoilValue } from 'recoil'; + +import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; +import { MainNavigationDrawerFixedItems } from '@/navigation/components/MainNavigationDrawerFixedItems'; +import { MainNavigationDrawerScrollableItems } from '@/navigation/components/MainNavigationDrawerScrollableItems'; +import { SupportDropdown } from '@/support/components/SupportDropdown'; +import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer'; +import { NavigationDrawerFixedContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent'; +import { NavigationDrawerScrollableContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent'; + +export const MainNavigationDrawer = ({ className }: { className?: string }) => { + const currentWorkspace = useRecoilValue(currentWorkspaceState); + + return ( + + + + + + + + + + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerFixedItems.tsx b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerFixedItems.tsx new file mode 100644 index 000000000..56a976f5f --- /dev/null +++ b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerFixedItems.tsx @@ -0,0 +1,52 @@ +import { useOpenRecordsSearchPageInCommandMenu } from '@/command-menu/hooks/useOpenRecordsSearchPageInCommandMenu'; +import { SettingsPath } from '@/types/SettingsPath'; +import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; +import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded'; +import { navigationDrawerExpandedMemorizedState } from '@/ui/navigation/states/navigationDrawerExpandedMemorizedState'; +import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; +import { useLingui } from '@lingui/react/macro'; +import { useLocation } from 'react-router-dom'; +import { useRecoilState, useSetRecoilState } from 'recoil'; +import { IconSearch, IconSettings } from 'twenty-ui/display'; +import { useIsMobile } from 'twenty-ui/utilities'; +import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; + +export const MainNavigationDrawerFixedItems = () => { + const isMobile = useIsMobile(); + const location = useLocation(); + const setNavigationMemorizedUrl = useSetRecoilState( + navigationMemorizedUrlState, + ); + + const [isNavigationDrawerExpanded, setIsNavigationDrawerExpanded] = + useRecoilState(isNavigationDrawerExpandedState); + const setNavigationDrawerExpandedMemorized = useSetRecoilState( + navigationDrawerExpandedMemorizedState, + ); + + const { t } = useLingui(); + + const { openRecordsSearchPage } = useOpenRecordsSearchPageInCommandMenu(); + return ( + !isMobile && ( + <> + + { + setNavigationDrawerExpandedMemorized(isNavigationDrawerExpanded); + setIsNavigationDrawerExpanded(true); + setNavigationMemorizedUrl(location.pathname + location.search); + }} + Icon={IconSettings} + /> + + ) + ); +}; diff --git a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx deleted file mode 100644 index d73e17615..000000000 --- a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { useLocation } from 'react-router-dom'; -import { useRecoilState, useSetRecoilState } from 'recoil'; - -import { useOpenRecordsSearchPageInCommandMenu } from '@/command-menu/hooks/useOpenRecordsSearchPageInCommandMenu'; -import { CurrentWorkspaceMemberFavoritesFolders } from '@/favorites/components/CurrentWorkspaceMemberFavoritesFolders'; -import { WorkspaceFavorites } from '@/favorites/components/WorkspaceFavorites'; -import { NavigationDrawerOpenedSection } from '@/object-metadata/components/NavigationDrawerOpenedSection'; -import { RemoteNavigationDrawerSection } from '@/object-metadata/components/RemoteNavigationDrawerSection'; -import { SettingsPath } from '@/types/SettingsPath'; -import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; -import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; -import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded'; -import { navigationDrawerExpandedMemorizedState } from '@/ui/navigation/states/navigationDrawerExpandedMemorizedState'; -import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; -import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; -import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -import styled from '@emotion/styled'; -import { useLingui } from '@lingui/react/macro'; -import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; -import { IconSearch, IconSettings } from 'twenty-ui/display'; - -const StyledMainSection = styled(NavigationDrawerSection)` - min-height: fit-content; -`; -const StyledInnerContainer = styled.div` - height: 100%; - width: 100%; -`; - -export const MainNavigationDrawerItems = () => { - const isMobile = useIsMobile(); - const location = useLocation(); - const setNavigationMemorizedUrl = useSetRecoilState( - navigationMemorizedUrlState, - ); - - const [isNavigationDrawerExpanded, setIsNavigationDrawerExpanded] = - useRecoilState(isNavigationDrawerExpandedState); - const setNavigationDrawerExpandedMemorized = useSetRecoilState( - navigationDrawerExpandedMemorizedState, - ); - - const { t } = useLingui(); - - const { openRecordsSearchPage } = useOpenRecordsSearchPageInCommandMenu(); - - return ( - <> - {!isMobile && ( - - - { - setNavigationDrawerExpandedMemorized(isNavigationDrawerExpanded); - setIsNavigationDrawerExpanded(true); - setNavigationMemorizedUrl(location.pathname + location.search); - }} - Icon={IconSettings} - /> - - )} - - - - - - - - - - ); -}; diff --git a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerScrollableItems.tsx b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerScrollableItems.tsx new file mode 100644 index 000000000..4bf7dce54 --- /dev/null +++ b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerScrollableItems.tsx @@ -0,0 +1,22 @@ +import { CurrentWorkspaceMemberFavoritesFolders } from '@/favorites/components/CurrentWorkspaceMemberFavoritesFolders'; +import { WorkspaceFavorites } from '@/favorites/components/WorkspaceFavorites'; +import { NavigationDrawerOpenedSection } from '@/object-metadata/components/NavigationDrawerOpenedSection'; +import { RemoteNavigationDrawerSection } from '@/object-metadata/components/RemoteNavigationDrawerSection'; +import styled from '@emotion/styled'; + +const StyledScrollableItemsContainer = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(3)}; +`; + +export const MainNavigationDrawerScrollableItems = () => { + return ( + + + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/navigation/components/SettingsNavigationDrawer.tsx b/packages/twenty-front/src/modules/navigation/components/SettingsNavigationDrawer.tsx new file mode 100644 index 000000000..129293990 --- /dev/null +++ b/packages/twenty-front/src/modules/navigation/components/SettingsNavigationDrawer.tsx @@ -0,0 +1,35 @@ +import { SettingsNavigationDrawerItems } from '@/settings/components/SettingsNavigationDrawerItems'; +import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer'; +import { NavigationDrawerFixedContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent'; +import { NavigationDrawerScrollableContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent'; +import { isAdvancedModeEnabledState } from '@/ui/navigation/navigation-drawer/states/isAdvancedModeEnabledState'; +import { useLingui } from '@lingui/react/macro'; +import { useRecoilState } from 'recoil'; +import { AdvancedSettingsToggle } from 'twenty-ui/navigation'; + +export const SettingsNavigationDrawer = ({ + className, +}: { + className?: string; +}) => { + const { t } = useLingui(); + const [isAdvancedModeEnabled, setIsAdvancedModeEnabled] = useRecoilState( + isAdvancedModeEnabledState, + ); + + return ( + + + + + + + + + + ); +}; diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx index 712cf02df..599096881 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItems.tsx @@ -9,16 +9,9 @@ import { NavigationDrawerItemGroup } from '@/ui/navigation/navigation-drawer/com import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; import { getNavigationSubItemLeftAdornment } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemLeftAdornment'; -import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -import styled from '@emotion/styled'; import { matchPath, resolvePath, useLocation } from 'react-router-dom'; import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; -const StyledInnerContainer = styled.div` - height: 100%; - width: 100%; -`; - export const SettingsNavigationDrawerItems = () => { const settingsNavigationItems: SettingsNavigationSection[] = useSettingsNavigationItems(); @@ -41,86 +34,81 @@ export const SettingsNavigationDrawerItems = () => { }; return ( - - - {settingsNavigationItems.map((section) => { - const allItemsHidden = section.items.every((item) => item.isHidden); - if (allItemsHidden) { - return null; - } + <> + {settingsNavigationItems.map((section) => { + const allItemsHidden = section.items.every((item) => item.isHidden); + if (allItemsHidden) { + return null; + } - return ( - - {section.isAdvanced ? ( - - - - ) : ( + return ( + + {section.isAdvanced ? ( + - )} - {section.items.map((item, index) => { - const subItems = item.subItems; - if (Array.isArray(subItems) && subItems.length > 0) { - const selectedSubItemIndex = - getSelectedIndexForSubItems(subItems); + + ) : ( + + )} + {section.items.map((item, index) => { + const subItems = item.subItems; + if (Array.isArray(subItems) && subItems.length > 0) { + const selectedSubItemIndex = + getSelectedIndexForSubItems(subItems); - return ( - + return ( + + + {subItems.map((subItem, subIndex) => ( - {subItems.map((subItem, subIndex) => ( - - ))} - - ); - } - return ( - + ))} + ); - })} - - ); - })} - - + } + return ( + + ); + })} + + ); + })} + ); }; diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInAppNavigationDrawerMock.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInAppNavigationDrawerMock.tsx index 397faa2b9..8bb9071dc 100644 --- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInAppNavigationDrawerMock.tsx +++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInAppNavigationDrawerMock.tsx @@ -1,5 +1,6 @@ import { SupportDropdown } from '@/support/components/SupportDropdown'; import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer'; +import { NavigationDrawerFixedContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent'; import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems'; import { SettingsPath } from '@/types/SettingsPath'; @@ -35,8 +36,8 @@ export const SignInAppNavigationDrawerMock = ({ const isMobile = useIsMobile(); const { t } = useLingui(); - const children = ( - <> + return ( + {!isMobile && ( - - ); - - const footer = ; - - return ( - - {children} + + + ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/page/components/DefaultLayout.tsx b/packages/twenty-front/src/modules/ui/layout/page/components/DefaultLayout.tsx index 8537c890c..f23c564ca 100644 --- a/packages/twenty-front/src/modules/ui/layout/page/components/DefaultLayout.tsx +++ b/packages/twenty-front/src/modules/ui/layout/page/components/DefaultLayout.tsx @@ -84,7 +84,7 @@ export const DefaultLayout = () => { ? (windowsWidth - (OBJECT_SETTINGS_WIDTH + NAV_DRAWER_WIDTHS.menu.desktop.expanded + - 64)) / + 76)) / 2 : 0, }} diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx index 2e859441e..727b46e60 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawer.tsx @@ -4,26 +4,24 @@ import { motion } from 'framer-motion'; import { ReactNode, useState } from 'react'; import { useRecoilValue } from 'recoil'; -import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { NAV_DRAWER_WIDTHS } from '@/ui/navigation/navigation-drawer/constants/NavDrawerWidths'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer'; -import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; import { isNavigationDrawerExpandedState } from '../../states/isNavigationDrawerExpanded'; import { NavigationDrawerBackButton } from './NavigationDrawerBackButton'; import { NavigationDrawerHeader } from './NavigationDrawerHeader'; import { MOBILE_VIEWPORT } from 'twenty-ui/theme'; export type NavigationDrawerProps = { - children: ReactNode; + children?: ReactNode; className?: string; - footer?: ReactNode; title: string; }; -const StyledAnimatedContainer = styled(motion.div)<{ isSettings?: boolean }>` +const StyledAnimatedContainer = styled(motion.div)` max-height: 100vh; - overflow: ${({ isSettings }) => (isSettings ? 'visible' : 'hidden')}; + overflow: hidden; `; const StyledContainer = styled.div<{ @@ -33,35 +31,26 @@ const StyledContainer = styled.div<{ box-sizing: border-box; display: flex; flex-direction: column; - width: ${NAV_DRAWER_WIDTHS.menu.desktop.expanded}px; + width: ${({ isSettings }) => + isSettings ? '100%' : NAV_DRAWER_WIDTHS.menu.desktop.expanded + 'px'}; gap: ${({ theme }) => theme.spacing(3)}; height: 100%; padding: ${({ theme, isSettings, isMobile }) => isSettings ? isMobile - ? theme.spacing(3, 8) - : theme.spacing(3, 8, 4, 0) - : theme.spacing(3, 2, 4)}; - padding-right: 0px; + ? theme.spacing(3, 0, 0, 8) + : theme.spacing(3, 0, 4, 0) + : theme.spacing(3, 0, 4, 2)}; @media (max-width: ${MOBILE_VIEWPORT}px) { width: 100%; - padding-left: 20px; - padding-right: 20px; + padding-left: ${({ theme }) => theme.spacing(5)}; + padding-right: ${({ theme }) => theme.spacing(5)}; } `; -const StyledItemsContainer = styled.div<{ isSettings?: boolean }>` - display: flex; - flex-direction: column; - margin-bottom: auto; - overflow: hidden; - flex: 1; -`; - export const NavigationDrawer = ({ children, className, - footer, title, }: NavigationDrawerProps) => { const [isHovered, setIsHovered] = useState(false); @@ -99,7 +88,6 @@ export const NavigationDrawer = ({ initial={false} animate={navigationDrawerAnimate} transition={{ duration: theme.animation.duration.normal }} - isSettings={isSettingsDrawer} > )} - - {children} - - {footer} + + {children} ); diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx index a8dc83796..a6090e528 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerBackButton.tsx @@ -39,6 +39,7 @@ const StyledContainer = styled.div` flex-direction: row; height: ${({ theme }) => theme.spacing(8)}; justify-content: space-between; + padding-left: ${({ theme }) => theme.spacing(5)}; `; export const NavigationDrawerBackButton = ({ diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx new file mode 100644 index 000000000..4a5b347a5 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent.tsx @@ -0,0 +1,33 @@ +import { ReactNode } from 'react'; + +import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer'; +import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; +import styled from '@emotion/styled'; +import { useIsMobile } from 'twenty-ui/utilities'; + +const StyledFixedContainer = styled.div<{ + isSettings?: boolean; + isMobile?: boolean; +}>` + ${({ isSettings, theme, isMobile }) => + isSettings + ? ` + padding-left: ${theme.spacing(5)}; + padding-right: ${isMobile ? theme.spacing(5) : theme.spacing(8)}; +` + : ''} +`; +export const NavigationDrawerFixedContent = ({ + children, +}: { + children: ReactNode; +}) => { + const isSettingsDrawer = useIsSettingsDrawer(); + const isMobile = useIsMobile(); + + return ( + + {children} + + ); +}; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx new file mode 100644 index 000000000..b2ca78813 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerScrollableContent.tsx @@ -0,0 +1,48 @@ +import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer'; +import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; +import styled from '@emotion/styled'; +import { ReactNode } from 'react'; +import { useIsMobile } from 'twenty-ui/utilities'; + +const StyledItemsContainer = styled.div` + display: flex; + flex-direction: column; + margin-bottom: auto; + overflow: hidden; + flex: 1; +`; + +const StyledScrollableInnerContainer = styled.div<{ isMobile?: boolean }>` + height: 100%; + padding-left: ${({ theme }) => theme.spacing(5)}; + padding-right: ${({ theme, isMobile }) => + isMobile ? theme.spacing(5) : theme.spacing(8)}; +`; + +export const NavigationDrawerScrollableContent = ({ + children, +}: { + children: ReactNode; +}) => { + const isSettingsDrawer = useIsSettingsDrawer(); + const isMobile = useIsMobile(); + + return ( + + + {isSettingsDrawer ? ( + + {children} + + ) : ( + <>{children} + )} + + + ); +}; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx index 6a878c2bc..ccb18ba0c 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSection.tsx @@ -1,21 +1,22 @@ +import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer'; import styled from '@emotion/styled'; import { useIsMobile } from 'twenty-ui/utilities'; -const StyledSection = styled.div` +const StyledSection = styled.div<{ isSettingsDrawer?: boolean }>` + margin-bottom: ${({ theme, isSettingsDrawer }) => + isSettingsDrawer ? theme.spacing(3) : 0}; width: 100%; - margin-bottom: ${({ theme }) => theme.spacing(3)}; - flex-shrink: 1; `; const StyledSectionInnerContainerMinusScrollPadding = styled.div<{ isMobile: boolean; + isSettingsDrawer: boolean; }>` display: flex; flex-direction: column; gap: ${({ theme }) => theme.betweenSiblingsGap}; - width: calc( - 100% - ${({ isMobile, theme }) => (isMobile ? 0 : theme.spacing(2))} - ); + width: ${({ isMobile, theme, isSettingsDrawer }) => + `calc(100% - ${isMobile || isSettingsDrawer ? 0 : theme.spacing(2)})`}; `; export const NavigationDrawerSection = ({ @@ -24,9 +25,13 @@ export const NavigationDrawerSection = ({ children: React.ReactNode; }) => { const isMobile = useIsMobile(); + const isSettingsDrawer = useIsSettingsDrawer(); return ( - - + + {children} diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx index 524094fe0..023a7deb0 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawer.stories.tsx @@ -16,16 +16,8 @@ import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedM import { mockedWorkspaceMemberData } from '~/testing/mock-data/users'; import { CurrentWorkspaceMemberFavoritesFolders } from '@/favorites/components/CurrentWorkspaceMemberFavoritesFolders'; +import { NavigationDrawerFixedContent } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerFixedContent'; import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; -import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator'; -import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; -import jsonPage from '../../../../../../../package.json'; -import { NavigationDrawer } from '../NavigationDrawer'; -import { NavigationDrawerItem } from '../NavigationDrawerItem'; -import { NavigationDrawerItemGroup } from '../NavigationDrawerItemGroup'; -import { NavigationDrawerSection } from '../NavigationDrawerSection'; -import { NavigationDrawerSectionTitle } from '../NavigationDrawerSectionTitle'; -import { GithubVersionLink } from 'twenty-ui/navigation'; import { IconAt, IconBell, @@ -42,7 +34,16 @@ import { IconUserCircle, IconUsers, } from 'twenty-ui/display'; +import { GithubVersionLink } from 'twenty-ui/navigation'; import { getOsControlSymbol } from 'twenty-ui/utilities'; +import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator'; +import { getSettingsPath } from '~/utils/navigation/getSettingsPath'; +import jsonPage from '../../../../../../../package.json'; +import { NavigationDrawer } from '../NavigationDrawer'; +import { NavigationDrawerItem } from '../NavigationDrawerItem'; +import { NavigationDrawerItemGroup } from '../NavigationDrawerItemGroup'; +import { NavigationDrawerSection } from '../NavigationDrawerSection'; +import { NavigationDrawerSectionTitle } from '../NavigationDrawerSectionTitle'; const meta: Meta = { title: 'UI/Navigation/NavigationDrawer/NavigationDrawer', @@ -71,7 +72,7 @@ const meta: Meta = { layout: 'fullscreen', msw: graphqlMocks, }, - argTypes: { children: { control: false }, footer: { control: false } }, + argTypes: { children: { control: false } }, }; export default meta; @@ -79,6 +80,7 @@ type Story = StoryObj; export const Default: Story = { args: { + title: 'Default', children: ( <> @@ -121,7 +123,6 @@ export const Default: Story = { ), - footer: null, }, play: async () => { const canvas = within(document.body); @@ -191,9 +192,12 @@ export const Settings: Story = { Icon={IconServer} /> + + + + ), - footer: , }, play: async () => { const canvas = within(document.body);