import { css } from '@emotion/react'; import { theme, typography, LinkBase } from '@expo/styleguide'; import { spacing } from '@expo/styleguide-base'; import { ArrowUpRightIcon } from '@expo/styleguide-icons'; import { useRouter } from 'next/compat/router'; import type { PropsWithChildren } from 'react'; import { useEffect, useRef } from 'react'; import { stripVersionFromPath } from '~/common/utilities'; import { NavigationRoute } from '~/types/common'; type SidebarLinkProps = PropsWithChildren<{ info: NavigationRoute; }>; const HEAD_NAV_HEIGHT = 160; const isLinkInViewport = (element: HTMLAnchorElement) => { const rect = element.getBoundingClientRect(); return ( rect.top - HEAD_NAV_HEIGHT >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); }; export const SidebarLink = ({ info, children }: SidebarLinkProps) => { const router = useRouter(); const ref = useRef(null); const checkSelection = () => { // Special case for root url if (info.name === 'Introduction') { if (router?.asPath.match(/\/versions\/[\w.]+\/$/) || router?.asPath === '/versions/latest/') { return true; } } const linkUrl = stripVersionFromPath(info.as || info.href); return ( linkUrl === stripVersionFromPath(router?.pathname) || linkUrl === stripVersionFromPath(router?.asPath) ); }; const isSelected = checkSelection(); useEffect(() => { if (isSelected && ref?.current && !isLinkInViewport(ref?.current)) { setTimeout(() => ref?.current && ref.current.scrollIntoView({ behavior: 'smooth' }), 50); } }, []); if (info.hidden) { return null; } const customDataAttributes = isSelected && { 'data-sidebar-anchor-selected': true, }; const isExternal = info.href.startsWith('http'); return (
{children} {isExternal && }
); }; const STYLES_LINK = css` ${typography.fontSizes[14]} display: flex; flex-direction: row; text-decoration: none; color: ${theme.text.secondary}; transition: 50ms ease color; align-items: center; scroll-margin: 60px; width: 100%; margin-left: -${spacing[2] + spacing[0.5]}px; &:hover { color: ${theme.text.link}; } &:hover svg { color: ${theme.button.tertiary.icon}; } `; const STYLES_LINK_ACTIVE = css` color: ${theme.text.link}; `; const STYLES_CONTAINER = css` display: flex; min-height: 32px; align-items: center; padding: ${spacing[1]}px; padding-right: ${spacing[2]}px; `; const STYLES_BULLET = css` height: 6px; width: 6px; min-height: 6px; min-width: 6px; border-radius: 100%; margin: ${spacing[2]}px ${spacing[1.5]}px; align-self: self-start; `; const STYLES_ACTIVE_BULLET = css` background-color: ${theme.text.link}; `;