1import { css } from '@emotion/react'; 2import { breakpoints } from '@expo/styleguide'; 3import React, { PropsWithChildren, ReactNode } from 'react'; 4 5import { LayoutScroll } from './LayoutScroll'; 6 7type LayoutProps = PropsWithChildren<{ 8 /** The content within the top bar that spans the columns */ 9 header: ReactNode; 10 /** The content within the left column */ 11 navigation?: ReactNode; 12 /** The content within the right column */ 13 sidebar?: ReactNode; 14}>; 15 16export function Layout({ header, navigation, sidebar, children }: LayoutProps) { 17 return ( 18 <div css={layoutStyle}> 19 <div css={headerStyle}>{header}</div> 20 <div css={navigationStyle}>{navigation}</div> 21 <div css={contentStyle}> 22 <LayoutScroll> 23 <div css={innerContentStyle}>{children}</div> 24 </LayoutScroll> 25 </div> 26 <div css={sidebarStyle}>{sidebar}</div> 27 </div> 28 ); 29} 30 31const layoutStyle = css({ 32 display: 'grid', 33 height: '100vh', 34 gridTemplateRows: '60px calc(100vh - 60px)', 35 gridTemplateColumns: 'min-content auto min-content', 36 gridTemplateAreas: ` 37 "header header header" 38 "navigation content sidebar" 39 `, 40}); 41 42const headerStyle = css({ gridArea: 'header' }); 43 44const navigationStyle = css({ 45 gridArea: 'navigation', 46 [`@media screen and (max-width: 768px)`]: { 47 display: 'none', 48 }, 49}); 50 51const contentStyle = css({ gridArea: 'content' }); 52const innerContentStyle = css({ 53 margin: '0 auto', 54 maxWidth: breakpoints.large, 55 height: '100%', 56 overflowY: 'visible', 57}); 58 59const sidebarStyle = css({ 60 gridArea: 'sidebar', 61 [`@media screen and (max-width: ${breakpoints.medium}px)`]: { 62 display: 'none', 63 }, 64}); 65