1import { css } from '@emotion/react';
2import { theme, typography, spacing } from '@expo/styleguide';
3import NextLink from 'next/link';
4import { useRouter } from 'next/router';
5import * as React from 'react';
6
7import stripVersionFromPath from '~/common/stripVersionFromPath';
8import { NavigationRoute } from '~/types/common';
9
10type SidebarLinkProps = React.PropsWithChildren<{
11  info: NavigationRoute;
12}>;
13
14export const SidebarLink = ({ info, children }: SidebarLinkProps) => {
15  const { asPath, pathname } = useRouter();
16
17  if (info.hidden) {
18    return null;
19  }
20
21  const checkSelection = () => {
22    // Special case for root url
23    if (info.name === 'Introduction') {
24      if (asPath.match(/\/versions\/[\w.]+\/$/) || asPath === '/versions/latest/') {
25        return true;
26      }
27    }
28
29    const linkUrl = stripVersionFromPath(info.as || info.href);
30    return linkUrl === stripVersionFromPath(pathname) || linkUrl === stripVersionFromPath(asPath);
31  };
32
33  const isSelected = checkSelection();
34
35  const customDataAttributes = isSelected
36    ? {
37        'data-sidebar-anchor-selected': true,
38      }
39    : {};
40
41  return (
42    <div css={STYLES_CONTAINER}>
43      <NextLink href={info.href as string} as={info.as || info.href} passHref>
44        <a {...customDataAttributes} css={[STYLES_LINK, isSelected && STYLES_LINK_ACTIVE]}>
45          {isSelected && <div css={STYLES_ACTIVE_BULLET} />}
46          {children}
47        </a>
48      </NextLink>
49    </div>
50  );
51};
52
53const STYLES_LINK = css`
54  ${typography.fontSizes[14]}
55  display: flex;
56  flex-direction: row;
57  text-decoration: none;
58  color: ${theme.text.secondary};
59  transition: 50ms ease color;
60  align-items: flex-start;
61  padding-left: ${spacing[4] + spacing[0.5]}px;
62
63  &:hover {
64    color: ${theme.link.default};
65  }
66`;
67
68const STYLES_LINK_ACTIVE = css`
69  font-family: ${typography.fontFaces.medium};
70  color: ${theme.link.default};
71  padding-left: 0;
72`;
73
74const STYLES_CONTAINER = css`
75  display: flex;
76  min-height: 32px;
77  align-items: center;
78  padding: ${spacing[1]}px;
79  padding-right: ${spacing[2]}px;
80`;
81
82const STYLES_ACTIVE_BULLET = css`
83  height: 6px;
84  width: 6px;
85  min-height: 6px;
86  min-width: 6px;
87  background-color: ${theme.link.default};
88  border-radius: 100%;
89  margin: ${spacing[2]}px ${spacing[1.5]}px;
90`;
91