@papillonarts/components 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/build/index.ts +1 -0
  2. package/build/primer/Alert/Alert.mdx +88 -0
  3. package/build/primer/Alert/Alert.prop.ts +45 -0
  4. package/build/primer/Alert/Alert.tsx +101 -0
  5. package/build/primer/Alert/__tests__/Alert.int.story.tsx +86 -0
  6. package/build/primer/Alert/__tests__/Alert.int.test.ts +37 -0
  7. package/build/primer/Alert/index.ts +2 -0
  8. package/build/primer/Blankslate/Blankslate.mdx +57 -0
  9. package/build/primer/Blankslate/Blankslate.prop.ts +26 -0
  10. package/build/primer/Blankslate/Blankslate.tsx +26 -0
  11. package/build/primer/Blankslate/__tests__/Blankslate.int.story.tsx +43 -0
  12. package/build/primer/Blankslate/__tests__/Blankslate.int.test.ts +29 -0
  13. package/build/primer/Blankslate/index.ts +2 -0
  14. package/build/primer/BranchName/branch-name.scss +2 -2
  15. package/build/primer/Breadcrumb/Breadcrumb.mdx +23 -0
  16. package/build/primer/Breadcrumb/Breadcrumb.prop.ts +28 -0
  17. package/build/primer/Breadcrumb/Breadcrumb.tsx +57 -0
  18. package/build/primer/Breadcrumb/__tests__/Breadcrumb.int.story.tsx +40 -0
  19. package/build/primer/Breadcrumb/__tests__/Breadcrumb.int.test.ts +40 -0
  20. package/build/primer/Breadcrumb/index.ts +2 -0
  21. package/build/primer/Button/Button.mdx +239 -0
  22. package/build/primer/Button/Button.prop.ts +77 -0
  23. package/build/primer/Button/Button.scss +4 -4
  24. package/build/primer/Button/Button.tsx +91 -0
  25. package/build/primer/Button/ButtonGroup.scss +2 -2
  26. package/build/primer/Button/__tests__/Button.int.story.tsx +173 -0
  27. package/build/primer/Button/__tests__/Button.int.test.ts +191 -0
  28. package/build/primer/Button/index.ts +2 -0
  29. package/build/primer/Button/misc.scss +2 -2
  30. package/build/primer/Dropdown/Dropdown.mdx +19 -0
  31. package/build/primer/Dropdown/Dropdown.prop.ts +33 -0
  32. package/build/primer/Dropdown/Dropdown.tsx +102 -0
  33. package/build/primer/Dropdown/__tests__/Dropdown.int.story.tsx +43 -0
  34. package/build/primer/Dropdown/__tests__/Dropdown.int.test.ts +53 -0
  35. package/build/primer/Dropdown/index.ts +2 -0
  36. package/build/primer/ErrorBoundary/ErrorBoundary.prop.ts +5 -0
  37. package/build/primer/ErrorBoundary/ErrorBoundary.tsx +35 -0
  38. package/build/primer/ErrorBoundary/__tests__/ErrorBoundary.int.story.tsx +23 -0
  39. package/build/primer/ErrorBoundary/__tests__/ErrorBoundary.int.test.ts +9 -0
  40. package/build/primer/ErrorBoundary/index.ts +1 -0
  41. package/build/primer/Form/Checkbox/Checkbox.prop.ts +34 -0
  42. package/build/primer/Form/Checkbox/Checkbox.tsx +40 -0
  43. package/build/primer/Form/Checkbox/__tests__/Checkbox.int.story.tsx +50 -0
  44. package/build/primer/Form/Checkbox/__tests__/Checkbox.int.test.ts +23 -0
  45. package/build/primer/Form/Checkbox/index.ts +2 -0
  46. package/build/primer/Form/Input/Input.prop.ts +43 -0
  47. package/build/primer/Form/Input/Input.tsx +43 -0
  48. package/build/primer/Form/Input/__tests__/Input.int.story.tsx +54 -0
  49. package/build/primer/Form/Input/__tests__/Input.int.test.ts +15 -0
  50. package/build/primer/Form/Input/index.ts +2 -0
  51. package/build/primer/Form/Radio/Radio.prop.ts +30 -0
  52. package/build/primer/Form/Radio/Radio.tsx +38 -0
  53. package/build/primer/Form/Radio/__tests__/Radio.int.story.tsx +42 -0
  54. package/build/primer/Form/Radio/__tests__/Radio.int.test.ts +13 -0
  55. package/build/primer/Form/Radio/index.ts +2 -0
  56. package/build/primer/Form/form-control.scss +4 -4
  57. package/build/primer/Form/form-select.scss +4 -4
  58. package/build/primer/Form/index.ts +19 -0
  59. package/build/primer/Grid/DisplayTable/DisplayTable.prop.ts +21 -0
  60. package/build/primer/Grid/DisplayTable/DisplayTable.tsx +68 -0
  61. package/build/primer/Grid/DisplayTable/__tests__/DisplayTable.int.data.ts +289 -0
  62. package/build/primer/Grid/DisplayTable/__tests__/DisplayTable.int.story.tsx +27 -0
  63. package/build/primer/Grid/DisplayTable/__tests__/DisplayTable.int.test.ts +9 -0
  64. package/build/primer/Grid/DisplayTable/index.ts +1 -0
  65. package/build/primer/Grid/FlexGrid/FlexGrid.prop.ts +59 -0
  66. package/build/primer/Grid/FlexGrid/FlexGrid.tsx +274 -0
  67. package/build/primer/Grid/FlexGrid/__tests__/FlexGrid.int.data.ts +289 -0
  68. package/build/primer/Grid/FlexGrid/__tests__/FlexGrid.int.story.tsx +146 -0
  69. package/build/primer/Grid/FlexGrid/__tests__/FlexGrid.int.test.ts +46 -0
  70. package/build/primer/Grid/FlexGrid/index.ts +2 -0
  71. package/build/primer/Grid/index.ts +9 -0
  72. package/build/primer/Icon/Icon.part.ts +1289 -0
  73. package/build/primer/Icon/Icon.prop.ts +1337 -0
  74. package/build/primer/Icon/Icon.tsx +49 -0
  75. package/build/primer/Icon/__tests__/Icon.int.story.tsx +58 -0
  76. package/build/primer/Icon/__tests__/Icon.int.test.ts +13 -0
  77. package/build/primer/Icon/index.ts +2 -0
  78. package/build/primer/Label/Label.mdx +13 -0
  79. package/build/primer/Label/Label.prop.ts +31 -0
  80. package/build/primer/Label/Label.tsx +27 -0
  81. package/build/primer/Label/__tests__/Label.int.story.tsx +19 -0
  82. package/build/primer/Label/__tests__/Label.int.test.ts +9 -0
  83. package/build/primer/Label/index.ts +1 -0
  84. package/build/primer/Label/mixins.scss +3 -3
  85. package/build/primer/Layout/container.scss +1 -1
  86. package/build/primer/Layout/grid-offset.scss +1 -1
  87. package/build/primer/Layout/grid.scss +2 -2
  88. package/build/primer/Loader/Loader.mdx +31 -0
  89. package/build/primer/Loader/Loader.prop.ts +16 -0
  90. package/build/primer/Loader/Loader.tsx +43 -0
  91. package/build/primer/Loader/__tests__/Loader.int.story.tsx +34 -0
  92. package/build/primer/Loader/__tests__/Loader.int.test.ts +21 -0
  93. package/build/primer/Loader/index.ts +2 -0
  94. package/build/primer/Navigation/Menu/Menu.prop.ts +26 -0
  95. package/build/primer/Navigation/Menu/Menu.tsx +42 -0
  96. package/build/primer/Navigation/Menu/__tests__/Menu.int.story.tsx +55 -0
  97. package/build/primer/Navigation/Menu/__tests__/Menu.int.test.ts +57 -0
  98. package/build/primer/Navigation/Menu/index.ts +1 -0
  99. package/build/primer/Navigation/TabNav/TabNav.prop.ts +39 -0
  100. package/build/primer/Navigation/TabNav/TabNav.tsx +105 -0
  101. package/build/primer/Navigation/TabNav/__tests__/TabNav.int.story.tsx +168 -0
  102. package/build/primer/Navigation/TabNav/__tests__/TabNav.int.test.ts +55 -0
  103. package/build/primer/Navigation/TabNav/index.ts +2 -0
  104. package/build/primer/Navigation/UnderlineNav/UnderlineNav.prop.ts +41 -0
  105. package/build/primer/Navigation/UnderlineNav/UnderlineNav.tsx +106 -0
  106. package/build/primer/Navigation/UnderlineNav/__tests__/UnderlineNav.int.story.tsx +140 -0
  107. package/build/primer/Navigation/UnderlineNav/__tests__/UnderlineNav.int.test.ts +81 -0
  108. package/build/primer/Navigation/UnderlineNav/index.ts +2 -0
  109. package/build/primer/Navigation/index.ts +12 -0
  110. package/build/primer/Pagination/PreviousNext/PreviousNext.prop.ts +53 -0
  111. package/build/primer/Pagination/PreviousNext/PreviousNext.scss +2 -2
  112. package/build/primer/Pagination/PreviousNext/PreviousNext.tsx +71 -0
  113. package/build/primer/Pagination/PreviousNext/__tests__/PreviousNext.int.story.tsx +48 -0
  114. package/build/primer/Pagination/PreviousNext/__tests__/PreviousNext.int.test.ts +15 -0
  115. package/build/primer/Pagination/PreviousNext/index.ts +2 -0
  116. package/build/primer/Pagination/index.ts +6 -0
  117. package/build/primer/Popover/Popover.mdx +190 -0
  118. package/build/primer/Popover/Popover.prop.ts +49 -0
  119. package/build/primer/Popover/Popover.tsx +80 -0
  120. package/build/primer/Popover/__tests__/Popover.int.story.tsx +216 -0
  121. package/build/primer/Popover/__tests__/Popover.int.test.ts +71 -0
  122. package/build/primer/Popover/index.ts +2 -0
  123. package/build/primer/Progress/Progress.mdx +31 -0
  124. package/build/primer/Progress/Progress.prop.ts +16 -0
  125. package/build/primer/Progress/Progress.tsx +19 -0
  126. package/build/primer/Progress/__tests__/Progress.int.story.tsx +28 -0
  127. package/build/primer/Progress/__tests__/Progress.int.test.ts +17 -0
  128. package/build/primer/Progress/index.ts +2 -0
  129. package/build/primer/Select/Select.mdx +19 -0
  130. package/build/primer/Select/Select.prop.ts +24 -0
  131. package/build/primer/Select/Select.scss +2 -2
  132. package/build/primer/Select/Select.tsx +58 -0
  133. package/build/primer/Select/__tests__/Select.int.story.tsx +38 -0
  134. package/build/primer/Select/__tests__/Select.int.test.ts +42 -0
  135. package/build/primer/Select/index.ts +2 -0
  136. package/build/primer/SelectMenu/SelectMenu.mdx +13 -0
  137. package/build/primer/SelectMenu/SelectMenu.prop.ts +25 -0
  138. package/build/primer/SelectMenu/SelectMenu.scss +4 -4
  139. package/build/primer/SelectMenu/SelectMenu.tsx +68 -0
  140. package/build/primer/SelectMenu/__tests__/SelectMenu.int.story.tsx +50 -0
  141. package/build/primer/SelectMenu/__tests__/SelectMenu.int.test.ts +56 -0
  142. package/build/primer/SelectMenu/index.ts +1 -0
  143. package/build/primer/Subhead/Subhead.mdx +20 -0
  144. package/build/primer/Subhead/Subhead.prop.ts +10 -0
  145. package/build/primer/Subhead/Subhead.scss +3 -3
  146. package/build/primer/Subhead/Subhead.tsx +15 -0
  147. package/build/primer/Subhead/__tests__/Subhead.int.story.tsx +23 -0
  148. package/build/primer/Subhead/__tests__/Subhead.int.test.ts +13 -0
  149. package/build/primer/Subhead/index.ts +1 -0
  150. package/build/primer/Toast/Toast.prop.ts +21 -0
  151. package/build/primer/Toast/Toast.scss +3 -3
  152. package/build/primer/Toast/Toast.tsx +38 -0
  153. package/build/primer/Toast/__tests__/Toast.int.story.tsx +50 -0
  154. package/build/primer/Toast/__tests__/Toast.int.test.ts +25 -0
  155. package/build/primer/Toast/index.ts +2 -0
  156. package/build/primer/index.ts +83 -0
  157. package/package.json +4 -4
  158. package/build/index.js +0 -12
  159. package/build/primer/Alert/Alert.js +0 -121
  160. package/build/primer/Alert/Alert.prop.js +0 -38
  161. package/build/primer/Alert/index.js +0 -19
  162. package/build/primer/Blankslate/Blankslate.js +0 -31
  163. package/build/primer/Blankslate/Blankslate.prop.js +0 -26
  164. package/build/primer/Blankslate/index.js +0 -19
  165. package/build/primer/Breadcrumb/Breadcrumb.js +0 -74
  166. package/build/primer/Breadcrumb/Breadcrumb.prop.js +0 -29
  167. package/build/primer/Breadcrumb/index.js +0 -19
  168. package/build/primer/Button/Button.js +0 -99
  169. package/build/primer/Button/Button.prop.js +0 -67
  170. package/build/primer/Button/index.js +0 -49
  171. package/build/primer/Dropdown/Dropdown.js +0 -104
  172. package/build/primer/Dropdown/Dropdown.prop.js +0 -34
  173. package/build/primer/Dropdown/index.js +0 -19
  174. package/build/primer/ErrorBoundary/ErrorBoundary.js +0 -59
  175. package/build/primer/ErrorBoundary/ErrorBoundary.prop.js +0 -11
  176. package/build/primer/ErrorBoundary/index.js +0 -12
  177. package/build/primer/Form/Checkbox/Checkbox.js +0 -49
  178. package/build/primer/Form/Checkbox/Checkbox.prop.js +0 -36
  179. package/build/primer/Form/Checkbox/index.js +0 -19
  180. package/build/primer/Form/Input/Input.js +0 -56
  181. package/build/primer/Form/Input/Input.prop.js +0 -43
  182. package/build/primer/Form/Input/index.js +0 -25
  183. package/build/primer/Form/Radio/Radio.js +0 -48
  184. package/build/primer/Form/Radio/Radio.prop.js +0 -34
  185. package/build/primer/Form/Radio/index.js +0 -19
  186. package/build/primer/Form/index.js +0 -24
  187. package/build/primer/Grid/DisplayTable/DisplayTable.js +0 -58
  188. package/build/primer/Grid/DisplayTable/DisplayTable.prop.js +0 -18
  189. package/build/primer/Grid/DisplayTable/index.js +0 -12
  190. package/build/primer/Grid/FlexGrid/FlexGrid.js +0 -244
  191. package/build/primer/Grid/FlexGrid/FlexGrid.prop.js +0 -49
  192. package/build/primer/Grid/FlexGrid/index.js +0 -25
  193. package/build/primer/Grid/index.js +0 -14
  194. package/build/primer/Icon/Icon.js +0 -70
  195. package/build/primer/Icon/Icon.part.js +0 -1295
  196. package/build/primer/Icon/Icon.prop.js +0 -689
  197. package/build/primer/Icon/index.js +0 -25
  198. package/build/primer/Label/Label.js +0 -31
  199. package/build/primer/Label/Label.prop.js +0 -34
  200. package/build/primer/Label/index.js +0 -12
  201. package/build/primer/Loader/Loader.js +0 -65
  202. package/build/primer/Loader/Loader.prop.js +0 -21
  203. package/build/primer/Loader/index.js +0 -19
  204. package/build/primer/Navigation/Menu/Menu.js +0 -70
  205. package/build/primer/Navigation/Menu/Menu.prop.js +0 -28
  206. package/build/primer/Navigation/Menu/index.js +0 -12
  207. package/build/primer/Navigation/TabNav/TabNav.js +0 -125
  208. package/build/primer/Navigation/TabNav/TabNav.prop.js +0 -36
  209. package/build/primer/Navigation/TabNav/index.js +0 -19
  210. package/build/primer/Navigation/UnderlineNav/UnderlineNav.js +0 -121
  211. package/build/primer/Navigation/UnderlineNav/UnderlineNav.prop.js +0 -41
  212. package/build/primer/Navigation/UnderlineNav/index.js +0 -25
  213. package/build/primer/Navigation/index.js +0 -17
  214. package/build/primer/Pagination/PreviousNext/PreviousNext.js +0 -76
  215. package/build/primer/Pagination/PreviousNext/PreviousNext.prop.js +0 -56
  216. package/build/primer/Pagination/PreviousNext/index.js +0 -19
  217. package/build/primer/Pagination/index.js +0 -11
  218. package/build/primer/Popover/Popover.js +0 -63
  219. package/build/primer/Popover/Popover.prop.js +0 -41
  220. package/build/primer/Popover/index.js +0 -25
  221. package/build/primer/Progress/Progress.js +0 -31
  222. package/build/primer/Progress/Progress.prop.js +0 -21
  223. package/build/primer/Progress/index.js +0 -19
  224. package/build/primer/Select/Select.js +0 -66
  225. package/build/primer/Select/Select.prop.js +0 -27
  226. package/build/primer/Select/index.js +0 -19
  227. package/build/primer/SelectMenu/SelectMenu.js +0 -95
  228. package/build/primer/SelectMenu/SelectMenu.prop.js +0 -26
  229. package/build/primer/SelectMenu/index.js +0 -12
  230. package/build/primer/Subhead/Subhead.js +0 -27
  231. package/build/primer/Subhead/Subhead.prop.js +0 -16
  232. package/build/primer/Subhead/index.js +0 -12
  233. package/build/primer/Toast/Toast.js +0 -55
  234. package/build/primer/Toast/Toast.prop.js +0 -26
  235. package/build/primer/Toast/index.js +0 -19
  236. package/build/primer/index.js +0 -87
  237. /package/build/primer/Form/Checkbox/{Checkbox.md → Checkbox.mdx} +0 -0
  238. /package/build/primer/Form/Checkbox/__tests__/__snapshots__/{Checkbox.int.test.js.snap → Checkbox.int.test.ts.snap} +0 -0
  239. /package/build/primer/Form/Input/{Input.md → Input.mdx} +0 -0
  240. /package/build/primer/Form/Input/__tests__/__snapshots__/{Input.int.test.js.snap → Input.int.test.ts.snap} +0 -0
  241. /package/build/primer/Form/Radio/{Radio.md → Radio.mdx} +0 -0
  242. /package/build/primer/Form/Radio/__tests__/__snapshots__/{Radio.int.test.js.snap → Radio.int.test.ts.snap} +0 -0
  243. /package/build/primer/Grid/DisplayTable/{DisplayTable.md → DisplayTable.mdx} +0 -0
  244. /package/build/primer/Grid/DisplayTable/__tests__/__snapshots__/{DisplayTable.int.test.js.snap → DisplayTable.int.test.ts.snap} +0 -0
  245. /package/build/primer/Grid/FlexGrid/{FlexGrid.md → FlexGrid.mdx} +0 -0
  246. /package/build/primer/Grid/FlexGrid/__tests__/__snapshots__/{FlexGrid.int.test.js.snap → FlexGrid.int.test.ts.snap} +0 -0
  247. /package/build/primer/Navigation/Menu/{Menu.md → Menu.mdx} +0 -0
  248. /package/build/primer/Navigation/Menu/__tests__/__snapshots__/{Menu.int.test.js.snap → Menu.int.test.ts.snap} +0 -0
  249. /package/build/primer/Navigation/TabNav/{TabNav.md → TabNav.mdx} +0 -0
  250. /package/build/primer/Navigation/TabNav/__tests__/__snapshots__/{TabNav.int.test.js.snap → TabNav.int.test.ts.snap} +0 -0
  251. /package/build/primer/Navigation/UnderlineNav/{UnderlineNav.md → UnderlineNav.mdx} +0 -0
  252. /package/build/primer/Navigation/UnderlineNav/__tests__/__snapshots__/{UnderlineNav.int.test.js.snap → UnderlineNav.int.test.ts.snap} +0 -0
  253. /package/build/primer/Pagination/PreviousNext/{PreviousNext.md → PreviousNext.mdx} +0 -0
  254. /package/build/primer/Pagination/PreviousNext/__tests__/__snapshots__/{PreviousNext.int.test.js.snap → PreviousNext.int.test.ts.snap} +0 -0
@@ -0,0 +1,105 @@
1
+ import { Fragment } from 'react'
2
+ import cx from 'classnames'
3
+ import { v1 as uuidv1 } from 'uuid'
4
+ import { getIndexItems, getIndexItemsWithSelected } from '@papillonarts/library/array'
5
+ import { TabNavProps, defaultProps, tabNavState } from './TabNav.prop'
6
+ import styles from './TabNav.scss'
7
+
8
+ export function TabNav({
9
+ className = defaultProps.className,
10
+ ariaAttr,
11
+ items,
12
+ actions = defaultProps.actions,
13
+ onClick,
14
+ children = defaultProps.children,
15
+ state = defaultProps.state,
16
+ }: TabNavProps) {
17
+ if (!items) {
18
+ return null
19
+ }
20
+
21
+ const { label, current } = ariaAttr
22
+ const indexItems = getIndexItems(items)
23
+
24
+ function renderActions() {
25
+ return <Fragment>{actions}</Fragment> // eslint-disable-line react/jsx-no-useless-fragment
26
+ }
27
+
28
+ return (
29
+ <div
30
+ className={cx(className, styles.tabnav, {
31
+ [styles['tabnav-inactive']]: state === tabNavState.inactive,
32
+ })}
33
+ >
34
+ {actions && renderActions()}
35
+ <nav className={styles['tabnav-tabs']} aria-label={label}>
36
+ {indexItems.map((indexItem) => {
37
+ const { href, text, link, isSelected, enabled, visible } = indexItem
38
+
39
+ const itemOtherProps = isSelected ? { ...{ 'aria-current': current } } : null
40
+
41
+ if (href && text) {
42
+ return (
43
+ <a
44
+ key={uuidv1()}
45
+ onClick={() => {
46
+ if (!enabled) {
47
+ return
48
+ }
49
+
50
+ const newIndexItems = getIndexItemsWithSelected(indexItems, indexItem)
51
+ onClick({
52
+ ariaAttr,
53
+ items: newIndexItems.map(
54
+ (newIndexItem) => (({ href, text, isSelected }) => ({ href, text, isSelected, enabled, visible }))(newIndexItem), // eslint-disable-line
55
+ ),
56
+ })
57
+ }}
58
+ className={styles['tabnav-tab']}
59
+ href={href}
60
+ {...itemOtherProps}
61
+ >
62
+ {text}
63
+ </a>
64
+ )
65
+ }
66
+
67
+ if (link) {
68
+ const Link = link.component
69
+
70
+ return (
71
+ <Link
72
+ key={uuidv1()}
73
+ onClick={() => {
74
+ if (!enabled) {
75
+ return
76
+ }
77
+
78
+ const newIndexItems = getIndexItemsWithSelected(indexItems, indexItem)
79
+ onClick({
80
+ ariaAttr,
81
+ items: newIndexItems.map(
82
+ (newIndexItem) =>
83
+ (({ link, isSelected, enabled, visible }) => ({ link, isSelected, enabled, visible }))(newIndexItem), // eslint-disable-line
84
+ ),
85
+ })
86
+ }}
87
+ className={cx(className, styles['tabnav-tab'], {
88
+ [styles['tabnav-tab-inactive']]: enabled === false,
89
+ [styles['tabnav-tab-hidden']]: visible === false,
90
+ })}
91
+ {...itemOtherProps}
92
+ {...link.props}
93
+ >
94
+ {link.children}
95
+ </Link>
96
+ )
97
+ }
98
+
99
+ return null
100
+ })}
101
+ </nav>
102
+ {children}
103
+ </div>
104
+ )
105
+ }
@@ -0,0 +1,168 @@
1
+ import cx from 'classnames'
2
+ import { v1 as uuidv1 } from 'uuid'
3
+ import { action } from 'storybook/actions'
4
+ import { withTests } from '@storybook/addon-jest'
5
+ import { BrowserRouter, Link } from 'react-router-dom'
6
+ import layoutStyles from '@papillonarts/css/build/primer/utilities/layout.scss'
7
+ import tabNavStyles from '../TabNav.scss'
8
+ import buttonStyles from '../../../Button/Button.scss'
9
+ import { tabNavState } from '../TabNav.prop'
10
+ import results from '../../../../../../../.jest-test-results.json'
11
+
12
+ const TabNav =
13
+ process.env.NODE_ENV === 'develop' || process.env.NODE_ENV === 'test'
14
+ ? require('../../../../index').primer.Navigation.TabNav
15
+ : require('../../../../../build').primer.Navigation.TabNav
16
+
17
+ export default {
18
+ title: 'Primer/Molecule/Navigation/TabNav',
19
+ component: TabNav,
20
+ decorators: [withTests({ results })],
21
+ parameters: { jest: ['TabNav.int.test.js'] },
22
+ excludeStories: ['ariaAttr', 'defaultItems', 'navigationItems', 'mixedEnabledVisibleItems', 'custom'],
23
+ }
24
+
25
+ export const ariaAttr = {
26
+ label: 'Foo bar',
27
+ current: 'page',
28
+ }
29
+
30
+ export const defaultItems = [
31
+ {
32
+ href: '#url',
33
+ text: 'Foo tab',
34
+ isSelected: true,
35
+ enabled: true,
36
+ visible: true,
37
+ },
38
+ { href: '#url', text: 'Bar tab', isSelected: false, enabled: true, visible: true },
39
+ ]
40
+
41
+ export const navigationItems = [
42
+ {
43
+ link: {
44
+ component: Link,
45
+ props: { ...{ to: '/foo' } },
46
+ children: 'Foo link',
47
+ },
48
+ isSelected: true,
49
+ enabled: true,
50
+ visible: true,
51
+ },
52
+ {
53
+ link: {
54
+ component: Link,
55
+ props: { ...{ to: '/bar' } },
56
+ children: 'Bar link',
57
+ },
58
+ isSelected: false,
59
+ enabled: true,
60
+ visible: true,
61
+ },
62
+ ]
63
+
64
+ export const mixedEnabledVisibleItems = [
65
+ {
66
+ link: {
67
+ component: Link,
68
+ props: { ...{ to: '/foo' } },
69
+ children: 'Foo link',
70
+ },
71
+ isSelected: true,
72
+ enabled: true,
73
+ visible: true,
74
+ },
75
+ {
76
+ link: {
77
+ component: Link,
78
+ props: { ...{ to: '/bar' } },
79
+ children: 'Bar link',
80
+ },
81
+ isSelected: false,
82
+ enabled: false,
83
+ visible: true,
84
+ },
85
+ {
86
+ link: {
87
+ component: Link,
88
+ props: { ...{ to: '/disco' } },
89
+ children: 'Disco link',
90
+ },
91
+ isSelected: false,
92
+ enabled: false,
93
+ visible: false,
94
+ },
95
+ ]
96
+
97
+ const actionButton = (
98
+ <a key={uuidv1()} className={cx(buttonStyles.btn, buttonStyles['btn-sm'], layoutStyles['float-right'])} href="#url" role="button">
99
+ Button
100
+ </a>
101
+ )
102
+
103
+ const buttonActions = [actionButton]
104
+
105
+ const actionText = (
106
+ <div key={uuidv1()} className={cx(tabNavStyles['tabnav-extra'], layoutStyles['float-right'])}>
107
+ Tabnav widget text here.
108
+ </div>
109
+ )
110
+
111
+ const textActions = [actionText]
112
+
113
+ const actionLink = (
114
+ <div key={uuidv1()} className={layoutStyles['float-right']}>
115
+ <a className={tabNavStyles['tabnav-extra']} href="#url">
116
+ Tabnav extra link
117
+ </a>
118
+ <a className={tabNavStyles['tabnav-extra']} href="#url">
119
+ Tabnav extra link
120
+ </a>
121
+ </div>
122
+ )
123
+
124
+ const linkActions = [actionLink]
125
+
126
+ export function custom(items, onClick) {
127
+ return (
128
+ <BrowserRouter>
129
+ <TabNav ariaAttr={ariaAttr} items={items} onClick={onClick} />
130
+ </BrowserRouter>
131
+ )
132
+ }
133
+
134
+ export function regular() {
135
+ return <TabNav ariaAttr={ariaAttr} items={defaultItems} onClick={action('onClick')} />
136
+ }
137
+
138
+ export function withButtonActions() {
139
+ return <TabNav ariaAttr={ariaAttr} items={defaultItems} actions={buttonActions} onClick={action('onClick')} />
140
+ }
141
+
142
+ export function withTextActions() {
143
+ return <TabNav ariaAttr={ariaAttr} items={defaultItems} actions={textActions} onClick={action('onClick')} />
144
+ }
145
+
146
+ export function withLinkActions() {
147
+ return <TabNav ariaAttr={ariaAttr} items={defaultItems} actions={linkActions} onClick={action('onClick')} />
148
+ }
149
+
150
+ export function withNavigation() {
151
+ return (
152
+ <BrowserRouter>
153
+ <TabNav ariaAttr={ariaAttr} items={navigationItems} onClick={action('onClick')} />
154
+ </BrowserRouter>
155
+ )
156
+ }
157
+
158
+ export function withMixedEnabledVisibleItems() {
159
+ return (
160
+ <BrowserRouter>
161
+ <TabNav ariaAttr={ariaAttr} items={mixedEnabledVisibleItems} onClick={action('onClick')} />
162
+ </BrowserRouter>
163
+ )
164
+ }
165
+
166
+ export function inactive() {
167
+ return <TabNav ariaAttr={ariaAttr} items={defaultItems} onClick={action('onClick')} state={tabNavState.inactive} />
168
+ }
@@ -0,0 +1,55 @@
1
+ import { defaultItems as items, regular, withButtonActions, withTextActions, withLinkActions, inactive } from './TabNav.int.story'
2
+
3
+ jest.mock('@papillonarts/library/array', () => ({
4
+ getIndexItems: () => {},
5
+ getIndexItemsWithSelected: () => {},
6
+ }))
7
+
8
+ const libraryArrayMockObject = require('@papillonarts/library/array')
9
+
10
+ describe('<TabNav />', () => {
11
+ const indexItemsDataObject = [
12
+ { ...items[0], index: 0 },
13
+ { ...items[1], index: 1 },
14
+ ]
15
+
16
+ const newIndexItemsWithSelectedDataObject = [
17
+ { ...items[0], index: 0, isSelected: true, enabled: true, visible: true },
18
+ { ...items[1], index: 1, isSelected: false, enabled: true, visible: true },
19
+ ]
20
+
21
+ function mockLibraryForRegularItems() {
22
+ jest.spyOn(libraryArrayMockObject, 'getIndexItems').mockReturnValue(indexItemsDataObject)
23
+
24
+ jest.spyOn(libraryArrayMockObject, 'getIndexItemsWithSelected').mockReturnValue(newIndexItemsWithSelectedDataObject)
25
+ }
26
+
27
+ afterEach(() => jest.clearAllMocks())
28
+
29
+ describe('Render', () => {
30
+ test('must match regular()', () => {
31
+ mockLibraryForRegularItems()
32
+ expect(global.renderToJSON(regular())).toMatchSnapshot()
33
+ })
34
+
35
+ test('must match withButtonActions()', () => {
36
+ mockLibraryForRegularItems()
37
+ expect(global.renderToJSON(withButtonActions())).toMatchSnapshot()
38
+ })
39
+
40
+ test('must match withTextActions()', () => {
41
+ mockLibraryForRegularItems()
42
+ expect(global.renderToJSON(withTextActions())).toMatchSnapshot()
43
+ })
44
+
45
+ test('must match withLinkActions()', () => {
46
+ mockLibraryForRegularItems()
47
+ expect(global.renderToJSON(withLinkActions())).toMatchSnapshot()
48
+ })
49
+
50
+ test('must match inactive()', () => {
51
+ mockLibraryForRegularItems()
52
+ expect(global.renderToJSON(inactive())).toMatchSnapshot()
53
+ })
54
+ })
55
+ })
@@ -0,0 +1,2 @@
1
+ export { TabNav } from './TabNav'
2
+ export { tabNavState } from './TabNav.prop'
@@ -0,0 +1,41 @@
1
+ export const underlineNavItemType = {
2
+ a: 'a',
3
+ button: 'button',
4
+ }
5
+
6
+ export const underlineNavAlignmentType = {
7
+ right: 'right',
8
+ left: 'left',
9
+ }
10
+
11
+ export const defaultProps = {
12
+ className: null,
13
+ actions: null,
14
+ align: 'left',
15
+ fullContainer: false,
16
+ }
17
+
18
+ export interface AriaAttrType {
19
+ label: string
20
+ selected: string
21
+ current: boolean | false | true | 'page' | 'step' | 'location' | 'date' | 'time'
22
+ }
23
+
24
+ export interface ItemType {
25
+ href: string
26
+ icon: string
27
+ text: string
28
+ html: React.ReactNode
29
+ isSelected: boolean
30
+ }
31
+
32
+ export interface UnderlineNavProps {
33
+ className?: string
34
+ ariaAttr: AriaAttrType
35
+ items: ItemType
36
+ itemType: typeof underlineNavItemType.a | typeof underlineNavItemType.button
37
+ actions?: React.ReactNode[]
38
+ align?: typeof underlineNavAlignmentType.right | typeof underlineNavAlignmentType.left
39
+ fullContainer?: boolean
40
+ onClick: (value) => void
41
+ }
@@ -0,0 +1,106 @@
1
+ import { Fragment } from 'react'
2
+ import cx from 'classnames'
3
+ import { v1 as uuidv1 } from 'uuid'
4
+ import { getIndexItems, getIndexItemsWithSelected } from '@papillonarts/library/array'
5
+ import { useState } from '@papillonarts/library/hooks'
6
+ import { UnderlineNavProps, defaultProps, underlineNavAlignmentType } from './UnderlineNav.prop'
7
+ import styles from './UnderlineNav.scss'
8
+ import containerStyles from '../../Layout/container.scss'
9
+ import { Icon, iconSize } from '../../Icon'
10
+
11
+ export function UnderlineNav({
12
+ className = defaultProps.className,
13
+ ariaAttr,
14
+ items,
15
+ itemType,
16
+ actions = defaultProps.actions,
17
+ align = defaultProps.align,
18
+ fullContainer = defaultProps.fullContainer,
19
+ onClick,
20
+ }: UnderlineNavProps) {
21
+ const [indexItems, setIndexItems] = useState(getIndexItems(items))
22
+ const { label, selected, current } = ariaAttr
23
+
24
+ function renderActions() {
25
+ return <div className={styles['UnderlineNav-actions']}>{actions}</div>
26
+ }
27
+
28
+ function renderBody() {
29
+ return (
30
+ <Fragment>
31
+ {align === underlineNavAlignmentType.right && actions && renderActions()}
32
+ <div className={styles['UnderlineNav-body']} role="tablist">
33
+ {indexItems.map((indexItem) => {
34
+ const { href, icon, text, html, isSelected } = indexItem
35
+ const anchorOtherProps = isSelected ? { ...{ 'aria-selected': selected } } : null
36
+ const buttonOtherProps = isSelected ? { ...{ 'aria-current': current } } : null
37
+
38
+ switch (itemType) {
39
+ case 'button':
40
+ return (
41
+ <button
42
+ key={uuidv1()}
43
+ onClick={(e) => {
44
+ e.preventDefault()
45
+ const newIndexItems = getIndexItemsWithSelected(indexItems, indexItem)
46
+ setIndexItems(newIndexItems)
47
+ onClick(newIndexItems)
48
+ }}
49
+ className={styles['UnderlineNav-item']}
50
+ role="tab"
51
+ type="button"
52
+ // @ts-ignore
53
+ href={href}
54
+ {...anchorOtherProps}
55
+ >
56
+ {icon && <Icon className={styles['UnderlineNav-octicon']} icon={icon} size={iconSize.small} />}
57
+ {html || null}
58
+ {text}
59
+ </button>
60
+ )
61
+ case 'a':
62
+ return (
63
+ <a
64
+ key={uuidv1()}
65
+ onClick={(e) => {
66
+ e.preventDefault()
67
+ const newIndexItems = getIndexItemsWithSelected(indexItems, indexItem)
68
+ setIndexItems(newIndexItems)
69
+ onClick(newIndexItems)
70
+ }}
71
+ className={styles['UnderlineNav-item']}
72
+ href={href}
73
+ {...buttonOtherProps}
74
+ >
75
+ {icon && <Icon className={styles['UnderlineNav-octicon']} icon={icon} size={iconSize.small} />}
76
+ {html || null}
77
+ {text}
78
+ </a>
79
+ )
80
+ default:
81
+ return null
82
+ }
83
+ })}
84
+ </div>
85
+ {align === underlineNavAlignmentType.left && actions && renderActions()}
86
+ </Fragment>
87
+ )
88
+ }
89
+
90
+ function renderBodyFullContainer() {
91
+ return <div className={cx(containerStyles['container-lg'], styles['UnderlineNav-container'])}>{renderBody()}</div>
92
+ }
93
+
94
+ return (
95
+ <nav
96
+ className={cx(className, styles.UnderlineNav, {
97
+ [styles['UnderlineNav--right']]: align === underlineNavAlignmentType.right,
98
+ [styles['UnderlineNav--full']]: fullContainer === true,
99
+ })}
100
+ aria-label={label}
101
+ >
102
+ {fullContainer === false && renderBody()}
103
+ {fullContainer === true && renderBodyFullContainer()}
104
+ </nav>
105
+ )
106
+ }
@@ -0,0 +1,140 @@
1
+ import { Fragment } from 'react'
2
+ import { v1 as uuidv1 } from 'uuid'
3
+ import { action } from 'storybook/actions'
4
+ import { withTests } from '@storybook/addon-jest'
5
+ import buttonStyles from '../../../Button/Button.scss'
6
+ import counterStyles from '../../../Label/counters.scss'
7
+ import { underlineNavItemType, underlineNavAlignmentType } from '../UnderlineNav.prop'
8
+ import { iconName } from '../../../Icon/Icon.prop'
9
+ import results from '../../../../../../../.jest-test-results.json'
10
+
11
+ const UnderlineNav =
12
+ process.env.NODE_ENV === 'develop' || process.env.NODE_ENV === 'test'
13
+ ? require('../../../../index').primer.Navigation.UnderlineNav
14
+ : require('../../../../../build').primer.Navigation.UnderlineNav
15
+
16
+ export default {
17
+ title: 'Primer/Molecule/Navigation/UnderlineNav',
18
+ component: UnderlineNav,
19
+ decorators: [withTests({ results })],
20
+ parameters: { jest: ['UnderlineNav.int.test.js'] },
21
+ excludeStories: ['ariaAttr', 'buttonItems', 'anchorItems', 'iconItems', 'fullContainerItems', 'custom'],
22
+ }
23
+
24
+ export const ariaAttr = {
25
+ label: 'Foo bar',
26
+ selected: 'true',
27
+ current: 'page',
28
+ }
29
+
30
+ export const buttonItems = [
31
+ { text: 'Item 1', isSelected: true },
32
+ { text: 'Item 2', isSelected: false },
33
+ { text: 'Item 3', isSelected: false },
34
+ { text: 'Item 4', isSelected: false },
35
+ ]
36
+
37
+ export const anchorItems = [
38
+ { href: '#url', text: 'Item 1', isSelected: true },
39
+ { href: '#url', text: 'Item 2', isSelected: false },
40
+ { href: '#url', text: 'Item 3', isSelected: false },
41
+ { href: '#url', text: 'Item 4', isSelected: false },
42
+ ]
43
+
44
+ export const iconItems = [
45
+ { href: '#url', icon: iconName.Tools16, html: <span>Item 1</span>, isSelected: true },
46
+ {
47
+ href: '#url',
48
+ icon: iconName.Tools16,
49
+ html: (
50
+ <Fragment>
51
+ <span>Item 2</span>
52
+ <span className={counterStyles.Counter}>10</span>
53
+ </Fragment>
54
+ ),
55
+ isSelected: false,
56
+ },
57
+ { href: '#url', icon: iconName.Tools16, html: <span>Item 3</span>, isSelected: false },
58
+ { href: '#url', icon: iconName.Tools16, html: <span>Item 4</span>, isSelected: false },
59
+ ]
60
+
61
+ export const fullContainerItems = [
62
+ { href: '#url', icon: iconName.Tools16, html: <span>Item 1</span>, isSelected: true },
63
+ {
64
+ href: '#url',
65
+ icon: iconName.Tools16,
66
+ html: (
67
+ <Fragment>
68
+ <span>Item 2</span>
69
+ <span className={counterStyles.Counter}>10</span>
70
+ </Fragment>
71
+ ),
72
+ isSelected: false,
73
+ },
74
+ { href: '#url', icon: iconName.Tools16, html: <span>Item 3</span>, isSelected: false },
75
+ { href: '#url', icon: iconName.Tools16, html: <span>Item 4</span>, isSelected: false },
76
+ ]
77
+
78
+ const actionButton = (
79
+ <a key={uuidv1()} href="#url" className={buttonStyles.btn}>
80
+ Button
81
+ </a>
82
+ )
83
+
84
+ const actions = [actionButton]
85
+
86
+ export function custom(items, itemType, onClick) {
87
+ return <UnderlineNav ariaAttr={ariaAttr} items={items} itemType={itemType} onClick={onClick} />
88
+ }
89
+
90
+ export function regular() {
91
+ return <UnderlineNav ariaAttr={ariaAttr} items={buttonItems} itemType={underlineNavItemType.button} onClick={action('onClick')} />
92
+ }
93
+
94
+ export function withActions() {
95
+ return (
96
+ <UnderlineNav ariaAttr={ariaAttr} items={anchorItems} itemType={underlineNavItemType.a} actions={actions} onClick={action('onClick')} />
97
+ )
98
+ }
99
+
100
+ export function rightAligned() {
101
+ return (
102
+ <UnderlineNav
103
+ ariaAttr={ariaAttr}
104
+ items={anchorItems}
105
+ itemType={underlineNavItemType.a}
106
+ align={underlineNavAlignmentType.right}
107
+ onClick={action('onClick')}
108
+ />
109
+ )
110
+ }
111
+
112
+ export function rightAlignedWithActions() {
113
+ return (
114
+ <UnderlineNav
115
+ ariaAttr={ariaAttr}
116
+ items={anchorItems}
117
+ itemType={underlineNavItemType.a}
118
+ align={underlineNavAlignmentType.right}
119
+ actions={actions}
120
+ onClick={action('onClick')}
121
+ />
122
+ )
123
+ }
124
+
125
+ export function withIcons() {
126
+ return <UnderlineNav ariaAttr={ariaAttr} items={iconItems} itemType={underlineNavItemType.a} onClick={action('onClick')} />
127
+ }
128
+
129
+ export function fullContainer() {
130
+ return (
131
+ <UnderlineNav
132
+ ariaAttr={ariaAttr}
133
+ items={fullContainerItems}
134
+ itemType={underlineNavItemType.a}
135
+ actions={actions}
136
+ fullContainer
137
+ onClick={action('onClick')}
138
+ />
139
+ )
140
+ }
@@ -0,0 +1,81 @@
1
+ import {
2
+ buttonItems,
3
+ regular,
4
+ withActions,
5
+ rightAligned,
6
+ rightAlignedWithActions,
7
+ withIcons,
8
+ fullContainer,
9
+ } from './UnderlineNav.int.story'
10
+
11
+ jest.mock('@papillonarts/library/array', () => ({
12
+ getIndexItems: () => {},
13
+ getIndexItemsWithSelected: () => {},
14
+ }))
15
+
16
+ jest.mock('@papillonarts/library/hooks', () => ({
17
+ useState: () => {},
18
+ }))
19
+
20
+ const libraryArrayMockObject = require('@papillonarts/library/array')
21
+ const libraryHooksMockObject = require('@papillonarts/library/hooks')
22
+
23
+ describe('<UnderlineNav />', () => {
24
+ let indexButtonItemsDataObject = [
25
+ { ...buttonItems[0], index: 0 },
26
+ { ...buttonItems[1], index: 1 },
27
+ { ...buttonItems[2], index: 2 },
28
+ { ...buttonItems[3], index: 3 },
29
+ ]
30
+
31
+ const newIndexButtonItemsWithSelectedDataObject = [
32
+ { ...buttonItems[0], index: 0, isSelected: true },
33
+ { ...buttonItems[1], index: 1, isSelected: false },
34
+ { ...buttonItems[2], index: 2, isSelected: false },
35
+ { ...buttonItems[3], index: 3, isSelected: false },
36
+ ]
37
+
38
+ const setIndexButtonItemsMockFn = jest.fn((indexButtonItems) => {
39
+ indexButtonItemsDataObject = indexButtonItems
40
+ })
41
+
42
+ function mockLibraryForButtonItems() {
43
+ jest.spyOn(libraryArrayMockObject, 'getIndexItems').mockReturnValue(indexButtonItemsDataObject)
44
+
45
+ jest.spyOn(libraryArrayMockObject, 'getIndexItemsWithSelected').mockReturnValue(newIndexButtonItemsWithSelectedDataObject)
46
+
47
+ jest.spyOn(libraryHooksMockObject, 'useState').mockImplementation(() => [indexButtonItemsDataObject, setIndexButtonItemsMockFn])
48
+ }
49
+
50
+ describe('Render', () => {
51
+ test('must match regular()', () => {
52
+ mockLibraryForButtonItems()
53
+ expect(global.renderToJSON(regular())).toMatchSnapshot()
54
+ })
55
+
56
+ test('must match withActions()', () => {
57
+ mockLibraryForButtonItems()
58
+ expect(global.renderToJSON(withActions())).toMatchSnapshot()
59
+ })
60
+
61
+ test('must match rightAligned()', () => {
62
+ mockLibraryForButtonItems()
63
+ expect(global.renderToJSON(rightAligned())).toMatchSnapshot()
64
+ })
65
+
66
+ test('must match rightAlignedWithActions()', () => {
67
+ mockLibraryForButtonItems()
68
+ expect(global.renderToJSON(rightAlignedWithActions())).toMatchSnapshot()
69
+ })
70
+
71
+ test('must match withIcons()', () => {
72
+ mockLibraryForButtonItems()
73
+ expect(global.renderToJSON(withIcons())).toMatchSnapshot()
74
+ })
75
+
76
+ test('must match fullContainer()', () => {
77
+ mockLibraryForButtonItems()
78
+ expect(global.renderToJSON(fullContainer())).toMatchSnapshot()
79
+ })
80
+ })
81
+ })