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.
 
 
 

138 lines
2.4 KiB

  1. import * as React from 'react'
  2. import styled from 'styled-components'
  3. import {applyBackgroundColor, minWidthFactor} from '../../utilities/mixins'
  4. import {configVar} from '../../utilities/helpers'
  5. const Base = styled('div')({
  6. position: 'fixed',
  7. top: 0,
  8. left: 0,
  9. width: '100%',
  10. height: 'var(--height-topbar, 4rem)',
  11. zIndex: 2,
  12. ...applyBackgroundColor(),
  13. '~ *': {
  14. paddingTop: 'var(--height-topbar, 4rem)',
  15. },
  16. '~ main ~ *': {
  17. paddingTop: 0,
  18. },
  19. ...minWidthFactor(3)({
  20. '~ main ~ *': {
  21. paddingTop: 'var(--height-topbar, 4rem)',
  22. },
  23. }),
  24. })
  25. const Container = styled('div')({
  26. padding: '0 1rem',
  27. boxSizing: 'border-box',
  28. margin: '0 auto',
  29. maxWidth: `calc(${configVar('base-width')} * 2)`,
  30. width: '100%',
  31. height: '100%',
  32. display: 'flex',
  33. alignItems: 'center',
  34. })
  35. const WideContainer = styled(Container)({
  36. ...minWidthFactor(3)({
  37. maxWidth: `calc(${configVar('base-width')} * 3)`,
  38. }),
  39. })
  40. const BrandContainer = styled('div')({
  41. })
  42. const CenterContainer = styled('div')({
  43. flex: 'auto',
  44. padding: '0 1rem',
  45. boxSizing: 'border-box',
  46. ':first-child': {
  47. paddingLeft: 0,
  48. },
  49. })
  50. const ActionContainer = styled('div')({
  51. display: 'flex',
  52. alignItems: 'center',
  53. justifyContent: 'flex-end',
  54. height: '100%',
  55. whiteSpace: 'nowrap',
  56. ...minWidthFactor(2)({
  57. minWidth: '8rem',
  58. }),
  59. })
  60. const LinkContainer = styled('div')({
  61. width: 'var(--height-topbar, 4rem)',
  62. height: '100%',
  63. '> *': {
  64. width: '100%',
  65. height: '100%',
  66. display: 'inline-grid',
  67. placeContent: 'center',
  68. },
  69. })
  70. const MenuLinkContainer = styled(LinkContainer)({
  71. ...minWidthFactor(3)({
  72. position: 'absolute',
  73. left: -999999,
  74. }),
  75. })
  76. type Props = {
  77. wide?: boolean,
  78. brand?: React.ReactNode,
  79. menuLink?: React.ReactNode,
  80. userLink?: React.ReactNode,
  81. }
  82. const TopBar: React.FC<Props> = ({
  83. wide,
  84. brand,
  85. menuLink,
  86. userLink,
  87. children,
  88. }) => {
  89. const ContainerComponent = wide ? WideContainer : Container
  90. return (
  91. <Base>
  92. <ContainerComponent>
  93. {
  94. Boolean(brand as unknown)
  95. && (
  96. <BrandContainer>
  97. {brand}
  98. </BrandContainer>
  99. )
  100. }
  101. <CenterContainer>
  102. {children}
  103. </CenterContainer>
  104. <ActionContainer>
  105. {
  106. Boolean(menuLink as unknown)
  107. && (
  108. <MenuLinkContainer>
  109. {menuLink}
  110. </MenuLinkContainer>
  111. )
  112. }
  113. {
  114. Boolean(userLink as unknown)
  115. && (
  116. <LinkContainer>
  117. {userLink}
  118. </LinkContainer>
  119. )
  120. }
  121. </ActionContainer>
  122. </ContainerComponent>
  123. </Base>
  124. )
  125. }
  126. export default TopBar