1import { css } from '@emotion/react'; 2import { theme, breakpoints, HamburgerIcon, iconSize, spacing } from '@expo/styleguide'; 3import React from 'react'; 4 5import { Search } from '../Search'; 6import { Logo } from './Logo'; 7import { ThemeSelector } from './ThemeSelector'; 8 9import { Button } from '~/ui/components/Button'; 10import { SidebarHead } from '~/ui/components/Sidebar'; 11import { BOLD } from '~/ui/components/Text'; 12 13type HeaderProps = { 14 sidebar: React.ReactNode; 15 sidebarActiveGroup: string; 16 isMobileMenuVisible: boolean; 17 setMobileMenuVisible: (isMobileMenuVisible: boolean) => void; 18}; 19 20export const Header = ({ 21 sidebar, 22 sidebarActiveGroup, 23 isMobileMenuVisible, 24 setMobileMenuVisible, 25}: HeaderProps) => { 26 return ( 27 <> 28 <nav css={[containerStyle, isMobileMenuVisible]}> 29 <div css={[columnStyle, leftColumnStyle]}> 30 <Logo /> 31 </div> 32 <div css={[columnStyle, rightColumnStyle]}> 33 <Search /> 34 <div css={hideOnMobileStyle}> 35 <ThemeSelector /> 36 </div> 37 <div css={showOnMobileStyle}> 38 <Button 39 theme="transparent" 40 css={[mobileButtonStyle, isMobileMenuVisible && mobileButtonActiveStyle]} 41 onClick={() => { 42 setMobileMenuVisible(!isMobileMenuVisible); 43 }}> 44 <HamburgerIcon size={iconSize.small} /> 45 </Button> 46 </div> 47 </div> 48 </nav> 49 {isMobileMenuVisible && ( 50 <nav css={[containerStyle, showOnMobileStyle]}> 51 <div css={[columnStyle, leftColumnStyle]}> 52 <BOLD>Theme</BOLD> 53 </div> 54 <div css={[columnStyle, rightColumnStyle]}> 55 <ThemeSelector /> 56 </div> 57 </nav> 58 )} 59 {isMobileMenuVisible && ( 60 <div css={mobileSidebarStyle}> 61 <SidebarHead sidebarActiveGroup={sidebarActiveGroup} /> 62 {sidebar} 63 </div> 64 )} 65 </> 66 ); 67}; 68 69const containerStyle = css` 70 display: flex; 71 align-items: center; 72 justify-content: flex-end; 73 position: relative; 74 background-color: ${theme.background.default}; 75 z-index: 2; 76 margin: 0 auto; 77 padding: 0 ${spacing[4]}px; 78 height: 60px; 79 box-sizing: border-box; 80 border-bottom: 1px solid ${theme.border.default}; 81 gap: ${spacing[4]}px; 82`; 83 84const columnStyle = css` 85 flex-shrink: 0; 86 display: flex; 87 background-color: transparent; 88`; 89 90const leftColumnStyle = css` 91 flex-grow: 1; 92 align-items: center; 93 94 @media screen and (max-width: ${(breakpoints.medium + breakpoints.large) / 2}px) { 95 flex-basis: auto; 96 width: auto; 97 } 98`; 99 100const rightColumnStyle = css` 101 justify-content: flex-end; 102 103 @media screen and (max-width: ${(breakpoints.medium + breakpoints.large) / 2}px) { 104 flex-basis: auto; 105 width: auto; 106 } 107`; 108 109const showOnMobileStyle = css` 110 display: none; 111 112 @media screen and (max-width: ${(breakpoints.medium + breakpoints.large) / 2}px) { 113 display: flex; 114 } 115`; 116 117const hideOnMobileStyle = css` 118 @media screen and (max-width: ${(breakpoints.medium + breakpoints.large) / 2}px) { 119 display: none; 120 } 121`; 122 123const mobileButtonStyle = css` 124 padding: 0 ${spacing[3]}px; 125 margin-left: ${spacing[2]}px; 126 127 &:hover { 128 background-color: ${theme.background.tertiary}; 129 box-shadow: none; 130 } 131`; 132 133const mobileButtonActiveStyle = css` 134 background-color: ${theme.background.secondary}; 135`; 136 137const mobileSidebarStyle = css` 138 background-color: ${theme.background.secondary}; 139 height: calc(100vh - (60px * 2)); 140 overflow-y: auto; 141 overflow-x: hidden; 142`; 143