Monorepo containing core modules of Zeichen.
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.

202 lines
3.9 KiB

  1. import * as React from 'react'
  2. import * as PropTypes from 'prop-types'
  3. import Link from 'next/link'
  4. import styled from 'styled-components'
  5. import Icon from '../Icon/Icon'
  6. const NoteLink = styled('a')({
  7. display: 'flex',
  8. textDecoration: 'none',
  9. color: 'inherit',
  10. alignItems: 'center',
  11. position: 'relative',
  12. flex: 'auto',
  13. padding: '0 1rem',
  14. boxSizing: 'border-box',
  15. })
  16. const NoteLinkPrimary = styled('span')({
  17. display: 'block',
  18. flex: 'auto',
  19. })
  20. const NoteLinkTitle = styled('strong')({
  21. display: 'block',
  22. height: '1.25em',
  23. position: 'relative',
  24. })
  25. const NoteLinkTitleOverflow = styled('span')({
  26. whiteSpace: 'nowrap',
  27. overflow: 'hidden',
  28. position: 'absolute',
  29. top: 0,
  30. left: 0,
  31. width: '100%',
  32. height: '100%',
  33. textOverflow: 'ellipsis',
  34. })
  35. const LinkContainer = styled('div')({
  36. position: 'relative',
  37. color: 'var(--color-primary, blue)',
  38. display: 'flex',
  39. alignItems: 'stretch',
  40. height: '4rem',
  41. })
  42. const NoteActions = styled('div')({
  43. display: 'flex',
  44. alignItems: 'stretch',
  45. height: '100%',
  46. position: 'relative',
  47. '@media (min-width: 1080px)': {
  48. opacity: 0,
  49. [`${LinkContainer}:hover &`]: {
  50. opacity: 1,
  51. },
  52. },
  53. })
  54. const NoteAction = styled('button')({
  55. height: '100%',
  56. width: '4rem',
  57. background: 'transparent',
  58. border: 0,
  59. color: 'inherit',
  60. cursor: 'pointer',
  61. outline: 0,
  62. padding: 0,
  63. })
  64. const NoteLinkBackground = styled('span')({
  65. '::before': {
  66. content: "''",
  67. position: 'absolute',
  68. top: 0,
  69. left: 0,
  70. width: '0.25rem',
  71. height: '100%',
  72. display: 'block',
  73. backgroundColor: 'currentColor',
  74. },
  75. '::after': {
  76. content: "''",
  77. opacity: 0.125,
  78. backgroundColor: 'currentColor',
  79. top: 0,
  80. left: 0,
  81. width: '100%',
  82. height: '100%',
  83. position: 'absolute',
  84. },
  85. })
  86. const IconContainer = styled('span')({
  87. display: 'inline-block',
  88. verticalAlign: 'middle',
  89. marginRight: '0.5rem',
  90. })
  91. const PostMeta = styled('small')({
  92. opacity: 0.5,
  93. height: '1.25rem',
  94. display: 'block',
  95. lineHeight: 1.25,
  96. })
  97. const propTypes = {
  98. active: PropTypes.bool,
  99. href: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
  100. replace: PropTypes.bool,
  101. iconName: PropTypes.string,
  102. title: PropTypes.string,
  103. subtitle: PropTypes.node,
  104. actions: PropTypes.arrayOf(PropTypes.shape({
  105. id: PropTypes.string.isRequired,
  106. onClick: PropTypes.func,
  107. iconName: PropTypes.string,
  108. })),
  109. }
  110. type Props = PropTypes.InferProps<typeof propTypes>
  111. const SecondaryNavItem: React.FC<Props> = ({
  112. active = false,
  113. href,
  114. replace = false,
  115. iconName,
  116. title,
  117. subtitle,
  118. actions,
  119. }) => (
  120. <LinkContainer>
  121. {
  122. active
  123. && (
  124. <NoteLinkBackground />
  125. )
  126. }
  127. <Link
  128. href={href}
  129. replace={replace}
  130. passHref
  131. shallow
  132. >
  133. <NoteLink>
  134. <IconContainer>
  135. {
  136. iconName
  137. && (
  138. <Icon
  139. name={iconName}
  140. />
  141. )
  142. }
  143. </IconContainer>
  144. <NoteLinkPrimary>
  145. <NoteLinkTitle
  146. style={{ opacity: title.length > 0 ? 1 : 0.5, }}
  147. >
  148. <NoteLinkTitleOverflow>
  149. {title.length > 0 ? title : '(untitled)'}
  150. </NoteLinkTitleOverflow>
  151. </NoteLinkTitle>
  152. {
  153. subtitle
  154. && (
  155. <React.Fragment>
  156. {' '}
  157. <PostMeta>
  158. {subtitle}
  159. </PostMeta>
  160. </React.Fragment>
  161. )
  162. }
  163. </NoteLinkPrimary>
  164. </NoteLink>
  165. </Link>
  166. {
  167. Array.isArray(actions)
  168. && (
  169. <NoteActions>
  170. {actions.map(a => (
  171. <NoteAction
  172. key={a.id}
  173. onClick={a.onClick}
  174. >
  175. <Icon
  176. name={a.iconName}
  177. />
  178. </NoteAction>
  179. ))}
  180. </NoteActions>
  181. )
  182. }
  183. </LinkContainer>
  184. )
  185. SecondaryNavItem.propTypes = propTypes
  186. export default SecondaryNavItem