Zeichen's app for both server and client.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

SecondaryNavItem.tsx 3.9 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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