1import { css } from '@emotion/react'; 2import { theme } from '@expo/styleguide'; 3import { spacing, breakpoints } from '@expo/styleguide-base'; 4import type { PropsWithChildren, ComponentType } from 'react'; 5 6import { SidebarGroup, SidebarSection, VersionSelector } from './index'; 7 8import { NavigationType, NavigationRoute } from '~/types/common'; 9 10const STYLES_SIDEBAR = css` 11 padding: ${spacing[4]}px; 12 width: 280px; 13 position: relative; 14 background-color: ${theme.background.default}; 15 16 @media screen and (max-width: ${breakpoints.medium + 124}px) { 17 width: 100%; 18 } 19`; 20 21const STYLES_SIDEBAR_FADE = css` 22 background: linear-gradient(${theme.background.default}, transparent); 23 height: 30px; 24 width: 274px; 25 position: fixed; 26 margin-top: -${spacing[4]}px; 27 left: 0; 28 z-index: 10; 29 pointer-events: none; 30 31 @media screen and (max-width: ${breakpoints.medium + 124}px) { 32 display: none; 33 } 34`; 35 36type SidebarProps = PropsWithChildren<{ 37 routes?: NavigationRoute[]; 38}>; 39 40export type SidebarNodeProps = { 41 route: NavigationRoute; 42 parentRoute?: NavigationRoute; 43}; 44 45export const Sidebar = ({ routes = [] }: SidebarProps) => { 46 const renderTypes: Record<NavigationType, ComponentType<SidebarNodeProps> | null> = { 47 section: SidebarGroup, 48 group: SidebarSection, 49 page: null, // Pages are rendered inside groups and should not be rendered directly 50 }; 51 52 return ( 53 <nav css={STYLES_SIDEBAR} data-sidebar> 54 <div css={[STYLES_SIDEBAR_FADE]} /> 55 <VersionSelector /> 56 {routes.map(route => { 57 const Component = renderTypes[route.type]; 58 return !!Component && <Component key={`${route.type}-${route.name}`} route={route} />; 59 })} 60 </nav> 61 ); 62}; 63