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.
 
 
 

130 lines
2.5 KiB

  1. import * as React from 'react'
  2. import styled, {createGlobalStyle} from 'styled-components'
  3. import TopBar from '../../widgets/TopBar'
  4. import {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. backgroundColor: 'var(--color-bg, white)',
  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 SidebarMainContainer = styled('div')({
  51. width: '100%',
  52. margin: '0 auto',
  53. padding: '0 1rem',
  54. boxSizing: 'border-box',
  55. maxWidth: `calc(${configVar('base-width')} * 2)`,
  56. [minWidthFactor(3)]: {
  57. width: `${configVar('base-width')}`,
  58. marginRight: 0,
  59. },
  60. })
  61. export const ContentContainer = styled('div')({
  62. padding: '0 1rem',
  63. boxSizing: 'border-box',
  64. width: '100%',
  65. maxWidth: `calc(${configVar('base-width')} * 2)`,
  66. marginRight: 'auto',
  67. marginLeft: 'auto',
  68. [minWidthFactor(3)]: {
  69. marginLeft: 0,
  70. },
  71. })
  72. type Props = {
  73. brand?: React.ReactNode,
  74. sidebarMain?: React.ReactChild,
  75. sidebarMainOpen?: boolean,
  76. menuLink?: React.ReactNode,
  77. userLink?: React.ReactNode,
  78. topBarCenter?: React.ReactChild,
  79. }
  80. export const Layout: React.FC<Props> = ({
  81. brand,
  82. sidebarMain,
  83. sidebarMainOpen,
  84. menuLink,
  85. userLink,
  86. topBarCenter,
  87. children,
  88. }) => {
  89. const LeftSidebarComponent = sidebarMainOpen ? OpenSidebarBase : SidebarBase
  90. return (
  91. <>
  92. <Config />
  93. {
  94. sidebarMainOpen
  95. && (
  96. <DisableScrolling />
  97. )
  98. }
  99. <TopBar
  100. span="wide"
  101. brand={brand}
  102. menuLink={menuLink}
  103. userLink={userLink}
  104. >
  105. {topBarCenter}
  106. </TopBar>
  107. <LeftSidebarComponent>
  108. <SidebarOverflow>
  109. {sidebarMain}
  110. </SidebarOverflow>
  111. </LeftSidebarComponent>
  112. <ContentBase>
  113. {children}
  114. </ContentBase>
  115. </>
  116. )
  117. }