Template for starting apps, powered by Next.js
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

150 lines
2.9 KiB

  1. import * as React from 'react';
  2. import styled, {createGlobalStyle} from 'styled-components';
  3. import TopBar from '../../widgets/TopBar';
  4. import {UrlObject} from 'url';
  5. const DisableScrolling = createGlobalStyle({
  6. 'body': {
  7. overflow: 'hidden',
  8. '@media (min-width: 1080px)': {
  9. overflow: 'auto',
  10. },
  11. },
  12. })
  13. const Main = styled('main')({
  14. boxSizing: 'border-box',
  15. '@media (min-width: 1080px)': {
  16. paddingLeft: 'calc(50% - var(--width-base, 360px) * 0.5)',
  17. },
  18. })
  19. const SidebarOverflow = styled('div')({
  20. width: '100%',
  21. height: '100%',
  22. overflow: 'auto',
  23. scrollbarWidth: 'none',
  24. '::-webkit-scrollbar': {
  25. display: 'none',
  26. },
  27. })
  28. const LeftSidebar = styled('div')({
  29. '--width-base': '360px',
  30. '--size-menu': '4rem',
  31. boxSizing: 'border-box',
  32. position: 'fixed',
  33. top: 0,
  34. left: '-100%',
  35. width: '100%',
  36. height: '100%',
  37. backgroundColor: 'var(--color-bg, white)',
  38. overflow: 'hidden',
  39. '@media (prefers-color-scheme: dark)': {
  40. backgroundColor: 'var(--color-bg, black)',
  41. },
  42. '@media (min-width: 1080px)': {
  43. width: 'calc(50% - var(--width-base, 360px) * 0.5)',
  44. left: 0,
  45. },
  46. })
  47. const OpenLeftSidebar = styled(LeftSidebar)({
  48. left: 0,
  49. })
  50. export const SidebarContainer = styled('div')({
  51. margin: '0 auto',
  52. padding: '0 1rem',
  53. boxSizing: 'border-box',
  54. maxWidth: 'calc(var(--width-base, 360px) * 2)',
  55. '@media (min-width: 1080px)': {
  56. width: 'var(--width-base, 360px)',
  57. marginRight: 0,
  58. },
  59. })
  60. export const Container = styled('div')({
  61. padding: '0 1rem',
  62. boxSizing: 'border-box',
  63. width: '100%',
  64. maxWidth: 'calc(var(--width-base, 360px) * 2)',
  65. marginRight: 'auto',
  66. marginLeft: 'auto',
  67. '@media (min-width: 1080px)': {
  68. marginLeft: 0,
  69. },
  70. })
  71. type Props = {
  72. query?: string,
  73. onSearch?: React.FormEventHandler,
  74. searchLabel?: string,
  75. searchName?: string,
  76. searchHint?: string,
  77. brand?: React.ReactNode,
  78. linkComponent?: React.ElementType,
  79. sidebarMain?: React.ReactChild,
  80. sidebarMainOpen?: boolean,
  81. menuLink?: UrlObject,
  82. userLink?: UrlObject,
  83. menuLinkLabel?: string,
  84. userLinkLabel?: string,
  85. }
  86. const LeftSidebarLayout: React.FC<Props> = ({
  87. query,
  88. sidebarMain,
  89. sidebarMainOpen,
  90. children,
  91. onSearch,
  92. searchLabel,
  93. searchName,
  94. searchHint,
  95. brand,
  96. linkComponent,
  97. menuLinkLabel,
  98. menuLink,
  99. userLink,
  100. userLinkLabel,
  101. }) => {
  102. const LeftSidebarComponent = sidebarMainOpen ? OpenLeftSidebar : LeftSidebar
  103. return (
  104. <>
  105. {
  106. sidebarMainOpen
  107. && (
  108. <DisableScrolling />
  109. )
  110. }
  111. <TopBar
  112. wide
  113. query={query}
  114. withMenu
  115. onSearch={onSearch}
  116. searchHint={searchHint}
  117. searchLabel={searchLabel}
  118. searchName={searchName}
  119. brand={brand}
  120. linkComponent={linkComponent}
  121. menuLink={menuLink}
  122. menuLinkLabel={menuLinkLabel}
  123. userLink={userLink}
  124. userLinkLabel={userLinkLabel}
  125. />
  126. <LeftSidebarComponent>
  127. <SidebarOverflow>
  128. {sidebarMain}
  129. </SidebarOverflow>
  130. </LeftSidebarComponent>
  131. <Main>
  132. {children}
  133. </Main>
  134. </>
  135. )
  136. }
  137. export default LeftSidebarLayout