Layout scaffolding for Web apps.
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.
 
 
 

129 lines
2.4 KiB

  1. import * as React from 'react'
  2. import styled, {createGlobalStyle} from 'styled-components'
  3. import TopBar from '../../widgets/TopBar'
  4. import {applyBackgroundColor, minWidthFactor} from '../../utilities/mixins'
  5. import {configVar, loadConfig} from '../../utilities/helpers'
  6. const Config = createGlobalStyle({
  7. ...loadConfig(),
  8. })
  9. const DisableScrolling = createGlobalStyle({
  10. 'body': {
  11. overflow: 'hidden',
  12. ...minWidthFactor(3)({
  13. overflow: 'auto',
  14. }),
  15. },
  16. })
  17. const ContentBase = styled('main')({
  18. boxSizing: 'border-box',
  19. ...minWidthFactor(3)({
  20. paddingLeft: `calc(50% - ${configVar('base-width')} * 0.5)`,
  21. }),
  22. })
  23. const SidebarOverflow = styled('div')({
  24. width: '100%',
  25. height: '100%',
  26. overflow: 'auto',
  27. // overflow: 'overlay',
  28. scrollbarWidth: 'none',
  29. '::-webkit-scrollbar': {
  30. display: 'none',
  31. },
  32. })
  33. const SidebarBase = styled('div')({
  34. boxSizing: 'border-box',
  35. position: 'fixed',
  36. top: 0,
  37. left: '-100%',
  38. width: '100%',
  39. height: '100%',
  40. overflow: 'hidden',
  41. ...applyBackgroundColor(),
  42. ...minWidthFactor(3)({
  43. width: `calc(50% - ${configVar('base-width')} * 0.5)`,
  44. left: 0,
  45. }),
  46. })
  47. const OpenSidebarBase = styled(SidebarBase)({
  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(${configVar('base-width')} * 2)`,
  55. ...minWidthFactor(3)({
  56. width: `${configVar('base-width')}`,
  57. marginRight: 0,
  58. }),
  59. })
  60. export const ContentContainer = styled('div')({
  61. padding: '0 1rem',
  62. boxSizing: 'border-box',
  63. width: '100%',
  64. maxWidth: `calc(${configVar('base-width')} * 2)`,
  65. marginRight: 'auto',
  66. marginLeft: 'auto',
  67. ...minWidthFactor(3)({
  68. marginLeft: 0,
  69. }),
  70. })
  71. type Props = {
  72. brand?: React.ReactNode,
  73. sidebarMain?: React.ReactChild,
  74. sidebarMainOpen?: boolean,
  75. menuLink?: React.ReactNode,
  76. userLink?: React.ReactNode,
  77. topBarCenter?: React.ReactChild,
  78. }
  79. export const Layout: React.FC<Props> = ({
  80. brand,
  81. sidebarMain,
  82. sidebarMainOpen,
  83. menuLink,
  84. userLink,
  85. topBarCenter,
  86. children,
  87. }) => {
  88. const LeftSidebarComponent = sidebarMainOpen ? OpenSidebarBase : SidebarBase
  89. return (
  90. <>
  91. <Config />
  92. {
  93. sidebarMainOpen
  94. && (
  95. <DisableScrolling />
  96. )
  97. }
  98. <TopBar
  99. wide
  100. brand={brand}
  101. menuLink={menuLink}
  102. userLink={userLink}
  103. >
  104. {topBarCenter}
  105. </TopBar>
  106. <LeftSidebarComponent>
  107. <SidebarOverflow>
  108. {sidebarMain}
  109. </SidebarOverflow>
  110. </LeftSidebarComponent>
  111. <ContentBase>
  112. {children}
  113. </ContentBase>
  114. </>
  115. )
  116. }