Skip to content

Commit

Permalink
add md sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
pettinarip committed Feb 17, 2024
1 parent b02b388 commit ca9dcec
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 19 deletions.
21 changes: 10 additions & 11 deletions src/components/UI/common/ApplicantsSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@ import NextLink from 'next/link';
import { PageText } from '..';

import { SidebarLink } from '../../../types';
import { useActiveHash } from '../../../hooks/useActiveHash';

interface Props {
sidebarLinks: SidebarLink[];
sectionsInView: boolean[];
}

export const ApplicantsSidebar: FC<Props> = ({ sidebarLinks, sectionsInView }) => {
const hrefs = sidebarLinks.map(({ href }) => href);
const activeHash = useActiveHash(hrefs);

// mark a sidebar link as active if previous one is not visible
// (by the iIntersection Observer) only, to avoid having more than 1 active link
const isActiveLink = (idx: number) => hrefs[idx] && !hrefs[idx - 1];
const isActiveLink = (idx: number) => sectionsInView[idx] && !sectionsInView[idx - 1];

return (
<Flex
display={{ base: 'none', lg: 'block' }}
Expand All @@ -36,16 +33,18 @@ export const ApplicantsSidebar: FC<Props> = ({ sidebarLinks, sectionsInView }) =
<Flex key={text} alignItems='center' mb={1}>
<Box
borderLeft='5px solid'
borderLeftColor={activeHash === href ? 'brand.accent' : 'transparent'}
borderLeftColor={isActiveLink(idx) ? 'brand.accent' : 'transparent'}
h='18px'
/>

<Box pl={3}>
<Link as={NextLink} href={href} _hover={{ textDecoration: 'none' }}>
<PageText fontWeight={400} lineHeight='28px' color='brand.orange.100'>
{text}
</PageText>
</Link>
<NextLink href={href}>
<Link href={href} _hover={{ textDecoration: 'none' }}>
<PageText fontWeight={400} lineHeight='28px' color='brand.orange.100'>
{text}
</PageText>
</Link>
</NextLink>
</Box>
</Flex>
))}
Expand Down
50 changes: 50 additions & 0 deletions src/components/UI/md/MdSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Box, Flex, Link } from '@chakra-ui/react';
import { FC, useMemo } from 'react';
import NextLink from 'next/link';

import { PageText } from '..';

import { SidebarLink } from '../../../types';
import { useActiveHash } from '../../../hooks/useActiveHash';

interface Props {
sidebarLinks: SidebarLink[];
}

export const MdSidebar: FC<Props> = ({ sidebarLinks }) => {
const hrefs = useMemo(() => sidebarLinks.map(({ href }) => href), [sidebarLinks]);
const activeHash = useActiveHash(hrefs, '0px');

return (
<Flex
display={{ base: 'none', lg: 'block' }}
bgGradient='linear(to-b, brand.sidebar.bgGradient.start 30%, brand.sidebar.bgGradient.end 100%)'
w='306px'
pt={12}
pl={14}
mt={-12}
top={0}
position='sticky'
alignSelf='flex-start'
h='45vh'
>
{sidebarLinks.map(({ text, href }, idx) => (
<Flex key={text} alignItems='center' mb={1}>
<Box
borderLeft='5px solid'
borderLeftColor={activeHash === href ? 'brand.accent' : 'transparent'}
h='18px'
/>

<Box pl={3}>
<Link as={NextLink} href={href} _hover={{ textDecoration: 'none' }}>
<PageText fontWeight={400} lineHeight='28px' color='brand.orange.100'>
{text}
</PageText>
</Link>
</Box>
</Flex>
))}
</Flex>
);
};
6 changes: 3 additions & 3 deletions src/components/layout/MdLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ReactNode } from 'react';
import { Box, Flex, Stack } from '@chakra-ui/react';

import { ApplicantsSidebar, PageMetadata } from '../UI';
import { PageMetadata } from '../UI';
import { MdSidebar } from '../UI/md/MdSidebar';

import type { Frontmatter, ToCNodeEntry, TocNodeType } from '../../types';

Expand All @@ -21,11 +22,10 @@ export const MdLayout = ({ children, frontmatter, tocNodeItems }: LayoutProps) =
<Box mx={{ md: 12 }} bg='white' position='relative' zIndex={1} mt={{ xl: 12 }}>
<Stack spacing={10} mb={8} px={{ base: 5, md: 0 }} py={{ base: 3, md: 12 }}>
<Flex>
<ApplicantsSidebar
<MdSidebar
sidebarLinks={tocNodeItems
.filter((item): item is ToCNodeEntry => !('items' in item))
.map(item => ({ text: item.title || '', href: item.url || '' }))}
sectionsInView={[]}
/>

<Box w={{ lg: '70%' }} px={{ md: 20 }} pr={{ lg: 12 }}>
Expand Down
13 changes: 8 additions & 5 deletions src/hooks/useActiveHash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import { useEffect, useState } from 'react';
* @returns id of the element currently in viewport
*/
export const useActiveHash = (itemIds: Array<string>, rootMargin = `0% 0% -80% 0%`): string => {
const [activeHash, setActiveHash] = useState(``);
const [hashes, setHashes] = useState<Record<string, boolean>>(() =>
itemIds.reduce((acc, id, index) => ({ [id]: index === 0, ...acc }), {})
);

useEffect(() => {
const observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
setActiveHash(`#${entry.target.id}`);
}
const hash = `#${entry.target.id}`;
setHashes(hashes => ({ ...hashes, [hash]: entry.isIntersecting }));
});
},
{ rootMargin }
Expand All @@ -39,5 +40,7 @@ export const useActiveHash = (itemIds: Array<string>, rootMargin = `0% 0% -80% 0
};
}, [itemIds, rootMargin]);

return activeHash;
const firstActiveHash = itemIds.find(id => hashes[id]);

return firstActiveHash || itemIds[0];
};

0 comments on commit ca9dcec

Please sign in to comment.