1import { css, Global } from '@emotion/react'; 2import { breakpoints, spacing, theme } from '@expo/styleguide'; 3import React, { PropsWithChildren, ReactNode } from 'react'; 4 5import { Header } from '~/ui/components/Header'; 6import { LayoutScroll } from '~/ui/components/Layout'; 7 8type LayoutProps = PropsWithChildren<{ 9 // The content within the top bar that spans the columns 10 header?: ReactNode; 11 // The content within the left column 12 navigation?: ReactNode; 13 // The content within the right column 14 sidebar?: ReactNode; 15}>; 16 17export const Layout = ({ header = <Header />, navigation, sidebar, children }: LayoutProps) => ( 18 <> 19 <Global 20 styles={css({ 21 // Ensure correct background for Overscroll 22 '[data-expo-theme="dark"] body': { 23 backgroundColor: theme.background.screen, 24 }, 25 })} 26 /> 27 <header css={headerStyle}>{header}</header> 28 <main css={layoutStyle}> 29 {navigation && <nav css={navigationStyle}>{navigation}</nav>} 30 <LayoutScroll> 31 <article css={innerContentStyle}>{children}</article> 32 </LayoutScroll> 33 {sidebar && <aside css={asideStyle}>{sidebar}</aside>} 34 </main> 35 </> 36); 37 38const HEADER_HEIGHT = 60; 39 40const layoutStyle = css({ 41 display: 'flex', 42 alignItems: 'stretch', 43 maxHeight: `calc(100vh - ${HEADER_HEIGHT}px)`, 44 marginTop: HEADER_HEIGHT, 45 backgroundColor: theme.background.default, 46 '[data-expo-theme="dark"] &': { 47 backgroundColor: theme.background.screen, 48 }, 49 [`@media screen and (max-width: ${breakpoints.medium}px)`]: { 50 // Ditch inner scroll on mobile, which results in weird bugs 51 maxHeight: 'none', 52 }, 53}); 54 55const headerStyle = css({ 56 position: 'fixed', 57 top: 0, 58 width: '100%', 59 height: HEADER_HEIGHT, 60 zIndex: 100, 61}); 62 63const navigationStyle = css({ 64 flexBasis: 256, 65 [`@media screen and (max-width: ${breakpoints.medium}px)`]: { 66 display: 'none', 67 }, 68}); 69 70const innerContentStyle = css({ 71 margin: '0 auto', 72 maxWidth: breakpoints.large, 73 padding: `${spacing[8]}px ${spacing[4]}px`, 74}); 75 76const asideStyle = css({ 77 flexBasis: 288, 78 [`@media screen and (max-width: ${breakpoints.medium}px)`]: { 79 display: 'none', 80 }, 81}); 82