diff --git a/components/Common/Breadcrumbs/index.tsx b/components/Common/Breadcrumbs/index.tsx index ce74dc88188ff..13c796305cb47 100644 --- a/components/Common/Breadcrumbs/index.tsx +++ b/components/Common/Breadcrumbs/index.tsx @@ -8,7 +8,7 @@ import BreadcrumbRoot from '@/components/Common/Breadcrumbs/BreadcrumbRoot'; import BreadcrumbTruncatedItem from '@/components/Common/Breadcrumbs/BreadcrumbTruncatedItem'; import type { FormattedMessage } from '@/types'; -type BreadcrumbLink = { +export type BreadcrumbLink = { label: FormattedMessage; href: string | undefined; }; diff --git a/components/withBreadcrumbs.tsx b/components/withBreadcrumbs.tsx index 91029a91520dd..d2a473cf7b2d5 100644 --- a/components/withBreadcrumbs.tsx +++ b/components/withBreadcrumbs.tsx @@ -2,16 +2,19 @@ import type { FC } from 'react'; +import type { BreadcrumbLink } from '@/components/Common/Breadcrumbs'; import Breadcrumbs from '@/components/Common/Breadcrumbs'; import { useClientContext, useMediaQuery, useSiteNavigation } from '@/hooks'; import type { NavigationKeys } from '@/types'; +import { dashToCamelCase } from '@/util/stringUtils'; const WithBreadcrumbs: FC = () => { const { navigationItems, getSideNavigation } = useSiteNavigation(); const { pathname } = useClientContext(); - const isMobileScreen = useMediaQuery('(max-width: 639px)'); + const maxLength = isMobileScreen ? 2 : 4; + const getBreadrumbs = () => { const [navigationKey] = navigationItems.find(([, item]) => pathname.includes(item.link)) || []; @@ -20,16 +23,36 @@ const WithBreadcrumbs: FC = () => { return []; } - return getSideNavigation([navigationKey as NavigationKeys]) - .map(([, item]) => item.items) - .flat() - .filter(([, item]) => pathname.includes(item.link)) - .map(([, item]) => ({ label: item.label, href: item.link })); + const navigationTree = getSideNavigation([navigationKey as NavigationKeys]); + + const pathList = pathname + .split('/') + .filter(item => item !== '') + .map(dashToCamelCase); + + let currentNode = navigationTree; + + // Reduce the pathList to a breadcrumbs array by finding each path in the current navigation layer, + // updating the currentNode to the found node's items(next layer) for the next iteration. + return pathList.reduce((breadcrumbs, path) => { + const nodeWithCurrentPath = currentNode.find( + ([nodePath]) => nodePath === path + ); + + if (nodeWithCurrentPath) { + const [, { label, link = '', items = [] }] = nodeWithCurrentPath; + + // Goes deeper on the tree of items if there are any. + currentNode = items; + + return label ? [...breadcrumbs, { label, href: link }] : breadcrumbs; + } + + return breadcrumbs; + }, [] as Array); }; - return ( - - ); + return ; }; export default WithBreadcrumbs; diff --git a/util/stringUtils.ts b/util/stringUtils.ts index 4dc48a046bf19..13c0007cf8b93 100644 --- a/util/stringUtils.ts +++ b/util/stringUtils.ts @@ -21,3 +21,8 @@ export const parseRichTextIntoPlainText = (richText: string) => .replace(/^[ ]+|[ ]+$/gm, '') // replaces leading numbers and dots from each line with an empty string .replace(/^\d+\.\s/gm, ''); + +export const dashToCamelCase = (str: string) => + str + .replace(/-([a-z])/g, (match, chr) => chr.toUpperCase()) + .replace(/^[A-Z]/, chr => chr.toLowerCase());