diff --git a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx index e28eb6bf83f4..367b121534d8 100644 --- a/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx +++ b/packages/twenty-front/src/modules/navigation/components/MainNavigationDrawerItems.tsx @@ -4,7 +4,7 @@ import { IconSearch, IconSettings } from 'twenty-ui'; import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { Favorites } from '@/favorites/components/Favorites'; -import { ObjectMetadataNavItems } from '@/object-metadata/components/ObjectMetadataNavItems'; +import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems'; import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection'; import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState'; @@ -41,8 +41,8 @@ export const MainNavigationDrawerItems = () => { - - + + ); }; diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems.tsx similarity index 73% rename from packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx rename to packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems.tsx index d65eb003b804..b2cffdd7b5f3 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItems.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems.tsx @@ -1,11 +1,10 @@ -import { AnimatePresence, motion } from 'framer-motion'; import { useLocation } from 'react-router-dom'; import { useRecoilValue } from 'recoil'; import { isDefined, useIcons } from 'twenty-ui'; import { currentUserState } from '@/auth/states/currentUserState'; import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; -import { ObjectMetadataNavItemsSkeletonLoader } from '@/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader'; +import { NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading'; import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; @@ -15,9 +14,9 @@ import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/compo import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle'; import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; import { useNavigationSection } from '@/ui/navigation/navigation-drawer/hooks/useNavigationSection'; +import { getNavigationSubItemState } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemState'; import { View } from '@/views/types/View'; import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews'; -import { Theme, useTheme } from '@emotion/react'; const ORDERED_STANDARD_OBJECTS = [ 'person', @@ -27,20 +26,11 @@ const ORDERED_STANDARD_OBJECTS = [ 'note', ]; -const navItemsAnimationVariants = (theme: Theme) => ({ - hidden: { - height: 0, - opacity: 0, - marginTop: 0, - }, - visible: { - height: 'auto', - opacity: 1, - marginTop: theme.spacing(1), - }, -}); - -export const ObjectMetadataNavItems = ({ isRemote }: { isRemote: boolean }) => { +export const NavigationDrawerSectionForObjectMetadataItems = ({ + isRemote, +}: { + isRemote: boolean; +}) => { const currentUser = useRecoilValue(currentUserState); const { toggleNavigationSection, isNavigationSectionOpenState } = @@ -57,13 +47,13 @@ export const ObjectMetadataNavItems = ({ isRemote }: { isRemote: boolean }) => { const { records: views } = usePrefetchedData(PrefetchKey.AllViews); const loading = useIsPrefetchLoading(); - const theme = useTheme(); const { getLastVisitedViewIdFromObjectMetadataItemId } = useLastVisitedView(); if (loading && isDefined(currentUser)) { - return ; + return ; } + // TODO: refactor this by splitting into separate components return ( filteredActiveObjectMetadataItems.length > 0 && ( @@ -121,6 +111,17 @@ export const ObjectMetadataNavItems = ({ isRemote }: { isRemote: boolean }) => { currentPath === `/objects/${objectMetadataItem.namePlural}` && objectMetadataViews.length > 1; + const sortedObjectMetadataViews = [...objectMetadataViews].sort( + (viewA, viewB) => + viewA.key === 'INDEX' ? -1 : viewA.position - viewB.position, + ); + + const selectedSubItemIndex = sortedObjectMetadataViews.findIndex( + (view) => viewId === view.id, + ); + + const subItemArrayLength = sortedObjectMetadataViews.length; + return (
{ currentPath === `/objects/${objectMetadataItem.namePlural}` } /> - - {shouldSubItemsBeDisplayed && ( - - {objectMetadataViews - .sort((viewA, viewB) => - viewA.key === 'INDEX' - ? -1 - : viewA.position - viewB.position, - ) - .map((view) => ( - - ))} - - )} - + {shouldSubItemsBeDisplayed && + sortedObjectMetadataViews.map((view, index) => ( + + ))}
); })} diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx new file mode 100644 index 000000000000..70e00d717330 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader.tsx @@ -0,0 +1,29 @@ +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; + +const StyledSkeletonColumn = styled.div` + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(1)}; + height: 76px; + padding-left: ${({ theme }) => theme.spacing(1)}; +`; + +export const NavigationDrawerSectionForObjectMetadataItemsSkeletonLoader: React.FC = + () => { + const theme = useTheme(); + return ( + + + + + + + + ); + }; diff --git a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader.tsx b/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader.tsx deleted file mode 100644 index 82669d907204..000000000000 --- a/packages/twenty-front/src/modules/object-metadata/components/ObjectMetadataNavItemsSkeletonLoader.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; -import { useTheme } from '@emotion/react'; -import styled from '@emotion/styled'; - -const StyledSkeletonColumn = styled.div` - display: flex; - flex-direction: column; - gap: ${({ theme }) => theme.spacing(1)}; - height: 76px; - padding-left: ${({ theme }) => theme.spacing(1)}; -`; - -export const ObjectMetadataNavItemsSkeletonLoader: React.FC = () => { - const theme = useTheme(); - return ( - - - - - - - - ); -}; diff --git a/packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx b/packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx index 7e74871a5fee..bb5f7e982580 100644 --- a/packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx +++ b/packages/twenty-front/src/modules/object-metadata/components/__stories__/ObjectMetadataNavItems.stories.tsx @@ -9,12 +9,12 @@ import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadat import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; +import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems'; import { PrefetchLoadedDecorator } from '~/testing/decorators/PrefetchLoadedDecorator'; -import { ObjectMetadataNavItems } from '../ObjectMetadataNavItems'; -const meta: Meta = { - title: 'Modules/ObjectMetadata/ObjectMetadataNavItems', - component: ObjectMetadataNavItems, +const meta: Meta = { + title: 'Modules/ObjectMetadata/NavigationDrawerSectionForObjectMetadataItems', + component: NavigationDrawerSectionForObjectMetadataItems, decorators: [ IconsProviderDecorator, ObjectMetadataItemsDecorator, @@ -29,7 +29,7 @@ const meta: Meta = { }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Default: Story = { play: async () => { diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts index 9e4a5c0c7e9e..b32a29f9aabb 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleToggleTrashColumnFilter.ts @@ -63,7 +63,7 @@ export const useHandleToggleTrashColumnFilter = ({ upsertCombinedViewFilter(newFilter); }, [ columnDefinitions, - objectMetadataItem.fields, + objectMetadataItem, objectNameSingular, upsertCombinedViewFilter, ]); diff --git a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx index 60733c0b60f9..050ca38f9e9b 100644 --- a/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx +++ b/packages/twenty-front/src/modules/settings/components/SettingsNavigationDrawerItem.tsx @@ -6,32 +6,38 @@ import { NavigationDrawerItem, NavigationDrawerItemProps, } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; +import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState'; type SettingsNavigationDrawerItemProps = Pick< NavigationDrawerItemProps, - 'Icon' | 'label' | 'level' | 'soon' + 'Icon' | 'label' | 'indentationLevel' | 'soon' > & { matchSubPages?: boolean; path: SettingsPath; + subItemState?: NavigationDrawerSubItemState; }; export const SettingsNavigationDrawerItem = ({ Icon, label, - level, + indentationLevel, matchSubPages = false, path, soon, + subItemState, }: SettingsNavigationDrawerItemProps) => { const href = getSettingsPagePath(path); + const pathName = useResolvedPath(href).pathname; + const isActive = !!useMatch({ - path: useResolvedPath(href).pathname, + path: pathName, end: !matchSubPages, }); return ( { const { signOut } = useAuth(); @@ -38,6 +53,39 @@ export const SettingsNavigationDrawerItems = () => { const isBillingPageEnabled = billing?.isBillingEnabled && !isFreeAccessEnabled; + // TODO: Refactor this part to only have arrays of navigation items + const currentPathName = useLocation().pathname; + + const accountSubSettings: SettingsNavigationItem[] = [ + { + label: 'Emails', + path: SettingsPath.AccountsEmails, + Icon: IconMail, + matchSubPages: true, + indentationLevel: 2, + }, + { + label: 'Calendars', + path: SettingsPath.AccountsCalendars, + Icon: IconCalendarEvent, + matchSubPages: true, + indentationLevel: 2, + }, + ]; + + const selectedIndex = accountSubSettings.findIndex((accountSubSetting) => { + const href = getSettingsPagePath(accountSubSetting.path); + const pathName = resolvePath(href).pathname; + + return matchPath( + { + path: pathName, + end: !accountSubSetting.matchSubPages, + }, + currentPathName, + ); + }); + return ( <> @@ -58,23 +106,21 @@ export const SettingsNavigationDrawerItems = () => { path={SettingsPath.Accounts} Icon={IconAt} /> - - + {accountSubSettings.map((navigationItem, index) => ( + + ))} - { /> )} - void; Icon: IconComponent; @@ -23,13 +30,10 @@ export type NavigationDrawerItemProps = { keyboard?: string[]; }; -type StyledItemProps = { - active?: boolean; - danger?: boolean; - level: 1 | 2; - soon?: boolean; - to?: string; -}; +type StyledItemProps = Pick< + NavigationDrawerItemProps, + 'active' | 'danger' | 'indentationLevel' | 'soon' | 'to' +>; const StyledItem = styled('div', { shouldForwardProp: (prop) => @@ -59,13 +63,17 @@ const StyledItem = styled('div', { font-family: 'Inter'; font-size: ${({ theme }) => theme.font.size.md}; gap: ${({ theme }) => theme.spacing(2)}; - margin-left: ${({ level, theme }) => theme.spacing((level - 1) * 4)}; + padding-bottom: ${({ theme }) => theme.spacing(1)}; padding-left: ${({ theme }) => theme.spacing(1)}; padding-right: ${({ theme }) => theme.spacing(1)}; padding-top: ${({ theme }) => theme.spacing(1)}; - pointer-events: ${(props) => (props.soon ? 'none' : 'auto')}; + margin-top: ${({ indentationLevel }) => + indentationLevel === 2 ? '2px' : '0'}; + + pointer-events: ${(props) => (props.soon ? 'none' : 'auto')}; + width: 100%; :hover { background: ${({ theme }) => theme.background.transparent.light}; color: ${(props) => @@ -116,10 +124,16 @@ const StyledKeyBoardShortcut = styled.div` visibility: hidden; `; +const StyledNavigationDrawerItemContainer = styled.div` + display: flex; + flex-grow: 1; + width: 100%; +`; + export const NavigationDrawerItem = ({ className, label, - level = 1, + indentationLevel = DEFAULT_INDENTATION_LEVEL, Icon, to, onClick, @@ -128,6 +142,7 @@ export const NavigationDrawerItem = ({ soon, count, keyboard, + subItemState, }: NavigationDrawerItemProps) => { const theme = useTheme(); const isMobile = useIsMobile(); @@ -136,6 +151,8 @@ export const NavigationDrawerItem = ({ isNavigationDrawerOpenState, ); + const showBreadcrumb = indentationLevel === 2; + const handleItemClick = () => { if (isMobile) { setIsNavigationDrawerOpen(false); @@ -152,26 +169,33 @@ export const NavigationDrawerItem = ({ }; return ( - - {Icon && } - {label} - {soon && } - {!!count && {count}} - {keyboard && ( - - {keyboard} - - )} - + + + {showBreadcrumb && ( + + )} + {Icon && ( + + )} + {label} + {soon && } + {!!count && {count}} + {keyboard && ( + + {keyboard} + + )} + + ); }; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx new file mode 100644 index 000000000000..47e8bd120864 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemBreadcrumb.tsx @@ -0,0 +1,79 @@ +import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState'; +import styled from '@emotion/styled'; + +export type NavigationDrawerItemBreadcrumbProps = { + state?: NavigationDrawerSubItemState; +}; + +const StyledNavigationDrawerItemBreadcrumbContainer = styled.div` + margin-left: 7.5px; + + height: 28px; + width: 9px; +`; + +const StyledGapVerticalLine = styled.div<{ darker: boolean }>` + background: ${({ theme, darker }) => + darker ? theme.font.color.tertiary : theme.border.color.strong}; + + position: relative; + top: -2px; + + height: 2px; + width: 1px; +`; + +const StyledSecondaryFullVerticalBar = styled.div<{ darker: boolean }>` + background: ${({ theme, darker }) => + darker ? theme.font.color.tertiary : theme.border.color.strong}; + + position: relative; + top: -17px; + height: 28px; + width: 1px; +`; + +const StyledRoundedProtrusion = styled.div<{ darker: boolean }>` + position: relative; + top: -2px; + + border-bottom-left-radius: 4px; + + border: 1px solid + ${({ theme, darker }) => + darker ? theme.font.color.tertiary : theme.border.color.strong}; + + ${({ darker }) => (darker ? 'z-index: 1;' : '')} + + border-top: none; + border-right: none; + height: 14px; + width: 8px; +`; + +export const NavigationDrawerItemBreadcrumb = ({ + state, +}: NavigationDrawerItemBreadcrumbProps) => { + const showVerticalBar = + state !== 'last-not-selected' && state !== 'last-selected'; + + const verticalBarShouldBeDarker = state === 'intermediate-before-selected'; + + const protrusionShouldBeDarker = + state === 'intermediate-selected' || state === 'last-selected'; + + const gapShouldBeDarker = + state === 'intermediate-before-selected' || + state === 'intermediate-selected' || + state === 'last-selected'; + + return ( + + + + {showVerticalBar && ( + + )} + + ); +}; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx index 3df470edb4e3..dfb9b5f7c61a 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerItemGroup.tsx @@ -3,7 +3,6 @@ import styled from '@emotion/styled'; const StyledGroup = styled.div` display: flex; flex-direction: column; - gap: ${({ theme }) => theme.spacing(0.5)}; `; export { StyledGroup as NavigationDrawerItemGroup }; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx index fad4149edbfd..4ef3f1c9654c 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem.tsx @@ -2,21 +2,12 @@ import { NavigationDrawerItem, NavigationDrawerItemProps, } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; -import styled from '@emotion/styled'; - -const StyledItem = styled.div` - &:not(:last-child) { - margin-bottom: ${({ theme }) => theme.spacing(0.5)}; - } - margin-left: ${({ theme }) => theme.spacing(4)}; -`; type NavigationDrawerSubItemProps = NavigationDrawerItemProps; export const NavigationDrawerSubItem = ({ className, label, - level = 1, Icon, to, onClick, @@ -25,22 +16,22 @@ export const NavigationDrawerSubItem = ({ soon, count, keyboard, + subItemState, }: NavigationDrawerSubItemProps) => { return ( - - - + ); }; 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 96d16a5526fe..f92d778e3b3f 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 @@ -23,6 +23,7 @@ import { GithubVersionLink } from '@/ui/navigation/link/components/GithubVersion import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator'; +import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem'; import { NavigationDrawer } from '../NavigationDrawer'; import { NavigationDrawerItem } from '../NavigationDrawerItem'; import { NavigationDrawerItemGroup } from '../NavigationDrawerItemGroup'; @@ -108,17 +109,17 @@ export const Submenu: Story = { to={getSettingsPagePath(SettingsPath.Accounts)} Icon={IconAt} /> - - diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx index f541a91aa615..81a0ffe4660b 100644 --- a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/components/__stories__/NavigationDrawerItem.stories.tsx @@ -37,6 +37,115 @@ export const Default: Story = { ], }; +export const Breadcrumb: Story = { + decorators: [ + (Story) => ( + +

Breadcrumb

+ + + + + + +
+ ), + ComponentWithRouterDecorator, + ], +}; + +export const BreadcrumbCatalog: CatalogStory< + Story, + typeof NavigationDrawerItem +> = { + decorators: [ + (Story) => ( + + + + ), + CatalogDecorator, + MemoryRouterDecorator, + ], + args: { + indentationLevel: 2, + }, + parameters: { + pseudo: { hover: ['.hover'] }, + catalog: { + dimensions: [ + { + name: 'subItemState', + values: [ + 'Intermediate before selected', + 'Intermediate selected', + 'Intermediate after selected', + 'Last not selected', + 'Last selected', + ], + props: (state: string) => { + switch (state) { + case 'Intermediate before selected': + return { subItemState: 'intermediate-before-selected' }; + case 'Intermediate selected': + return { subItemState: 'intermediate-selected' }; + case 'Intermediate after selected': + return { subItemState: 'intermediate-after-selected' }; + case 'Last not selected': + return { subItemState: 'last-not-selected' }; + case 'Last selected': + return { subItemState: 'last-selected' }; + default: + throw new Error(`Unknown state: ${state}`); + } + }, + }, + ], + }, + }, +}; + export const Catalog: CatalogStory = { decorators: [ (Story) => ( diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState.ts b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState.ts new file mode 100644 index 000000000000..7de9e4ef5675 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState.ts @@ -0,0 +1,6 @@ +export type NavigationDrawerSubItemState = + | 'intermediate-before-selected' + | 'intermediate-selected' + | 'intermediate-after-selected' + | 'last-selected' + | 'last-not-selected'; diff --git a/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/utils/getNavigationSubItemState.ts b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/utils/getNavigationSubItemState.ts new file mode 100644 index 000000000000..dcb08f78ee13 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/navigation/navigation-drawer/utils/getNavigationSubItemState.ts @@ -0,0 +1,35 @@ +import { NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState'; + +export const getNavigationSubItemState = ({ + index, + arrayLength, + selectedIndex, +}: { + index: number; + arrayLength: number; + selectedIndex: number; +}): NavigationDrawerSubItemState => { + const thereIsOnlyOneItem = arrayLength === 1; + + const itsTheLastItem = index === arrayLength - 1; + + const itsTheSelectedItem = index === selectedIndex; + + const itsBeforeTheSelectedItem = index < selectedIndex; + + if (thereIsOnlyOneItem || itsTheLastItem) { + if (itsTheSelectedItem) { + return 'last-selected'; + } else { + return 'last-not-selected'; + } + } else { + if (itsTheSelectedItem) { + return 'intermediate-selected'; + } else if (itsBeforeTheSelectedItem) { + return 'intermediate-before-selected'; + } else { + return 'intermediate-after-selected'; + } + } +};