@arbor-education/design-system.components 0.0.3 → 0.0.5

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 (274) hide show
  1. package/README.md +1 -1
  2. package/dist/components/button/Button.d.ts +5 -2
  3. package/dist/components/button/Button.d.ts.map +1 -1
  4. package/dist/components/button/Button.js +3 -1
  5. package/dist/components/button/Button.js.map +1 -1
  6. package/dist/components/card/Card.d.ts +1 -2
  7. package/dist/components/card/Card.d.ts.map +1 -1
  8. package/dist/components/card/Card.js +3 -3
  9. package/dist/components/card/Card.js.map +1 -1
  10. package/dist/components/card/Card.test.js +0 -5
  11. package/dist/components/card/Card.test.js.map +1 -1
  12. package/dist/components/formField/FormField.d.ts +4 -0
  13. package/dist/components/formField/FormField.d.ts.map +1 -1
  14. package/dist/components/formField/FormField.js +2 -1
  15. package/dist/components/formField/FormField.js.map +1 -1
  16. package/dist/components/formField/FormField.stories.d.ts.map +1 -1
  17. package/dist/components/formField/FormField.stories.js +3 -1
  18. package/dist/components/formField/FormField.stories.js.map +1 -1
  19. package/dist/components/formField/FormField.test.js +5 -0
  20. package/dist/components/formField/FormField.test.js.map +1 -1
  21. package/dist/components/formField/inputs/checkbox/CheckboxInput.d.ts +7 -0
  22. package/dist/components/formField/inputs/checkbox/CheckboxInput.d.ts.map +1 -0
  23. package/dist/components/formField/inputs/checkbox/CheckboxInput.js +31 -0
  24. package/dist/components/formField/inputs/checkbox/CheckboxInput.js.map +1 -0
  25. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.d.ts +17 -0
  26. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.d.ts.map +1 -0
  27. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.js +19 -0
  28. package/dist/components/formField/inputs/checkbox/CheckboxInput.stories.js.map +1 -0
  29. package/dist/components/formField/inputs/checkbox/CheckboxInput.test.d.ts +2 -0
  30. package/dist/components/formField/inputs/checkbox/CheckboxInput.test.d.ts.map +1 -0
  31. package/dist/components/formField/inputs/checkbox/CheckboxInput.test.js +30 -0
  32. package/dist/components/formField/inputs/checkbox/CheckboxInput.test.js.map +1 -0
  33. package/dist/components/formField/inputs/dropdown/Dropdown.d.ts +11 -0
  34. package/dist/components/formField/inputs/dropdown/Dropdown.d.ts.map +1 -0
  35. package/dist/components/formField/inputs/dropdown/Dropdown.js +43 -0
  36. package/dist/components/formField/inputs/dropdown/Dropdown.js.map +1 -0
  37. package/dist/components/formField/inputs/dropdown/Dropdown.stories.d.ts +161 -0
  38. package/dist/components/formField/inputs/dropdown/Dropdown.stories.d.ts.map +1 -0
  39. package/dist/components/formField/inputs/dropdown/Dropdown.stories.js +172 -0
  40. package/dist/components/formField/inputs/dropdown/Dropdown.stories.js.map +1 -0
  41. package/dist/components/formField/inputs/dropdown/Dropdown.test.d.ts +2 -0
  42. package/dist/components/formField/inputs/dropdown/Dropdown.test.d.ts.map +1 -0
  43. package/dist/components/formField/inputs/dropdown/Dropdown.test.js +93 -0
  44. package/dist/components/formField/inputs/dropdown/Dropdown.test.js.map +1 -0
  45. package/dist/components/formField/inputs/dropdown/buttons/dropdownButton/DropdownButton.d.ts +11 -0
  46. package/dist/components/formField/inputs/dropdown/buttons/dropdownButton/DropdownButton.d.ts.map +1 -0
  47. package/dist/components/formField/inputs/dropdown/buttons/dropdownButton/DropdownButton.js +15 -0
  48. package/dist/components/formField/inputs/dropdown/buttons/dropdownButton/DropdownButton.js.map +1 -0
  49. package/dist/components/formField/inputs/dropdown/items/DropdownItemRenderer.d.ts +10 -0
  50. package/dist/components/formField/inputs/dropdown/items/DropdownItemRenderer.d.ts.map +1 -0
  51. package/dist/components/formField/inputs/dropdown/items/DropdownItemRenderer.js +12 -0
  52. package/dist/components/formField/inputs/dropdown/items/DropdownItemRenderer.js.map +1 -0
  53. package/dist/components/formField/inputs/dropdown/items/dropdownItem/DropdownItem.d.ts +9 -0
  54. package/dist/components/formField/inputs/dropdown/items/dropdownItem/DropdownItem.d.ts.map +1 -0
  55. package/dist/components/formField/inputs/dropdown/items/dropdownItem/DropdownItem.js +17 -0
  56. package/dist/components/formField/inputs/dropdown/items/dropdownItem/DropdownItem.js.map +1 -0
  57. package/dist/components/formField/inputs/dropdown/items/dropdownMultiLineItem/DropdownMultiLineItem.d.ts +7 -0
  58. package/dist/components/formField/inputs/dropdown/items/dropdownMultiLineItem/DropdownMultiLineItem.d.ts.map +1 -0
  59. package/dist/components/formField/inputs/dropdown/items/dropdownMultiLineItem/DropdownMultiLineItem.js +16 -0
  60. package/dist/components/formField/inputs/dropdown/items/dropdownMultiLineItem/DropdownMultiLineItem.js.map +1 -0
  61. package/dist/components/formField/inputs/dropdown/wrapper/DropdownWrapper.d.ts +16 -0
  62. package/dist/components/formField/inputs/dropdown/wrapper/DropdownWrapper.d.ts.map +1 -0
  63. package/dist/components/formField/inputs/dropdown/wrapper/DropdownWrapper.js +73 -0
  64. package/dist/components/formField/inputs/dropdown/wrapper/DropdownWrapper.js.map +1 -0
  65. package/dist/components/formField/inputs/number/NumberInput.d.ts +6 -0
  66. package/dist/components/formField/inputs/number/NumberInput.d.ts.map +1 -0
  67. package/dist/components/formField/inputs/number/NumberInput.js +39 -0
  68. package/dist/components/formField/inputs/number/NumberInput.js.map +1 -0
  69. package/dist/components/formField/inputs/number/NumberInput.stories.d.ts +20 -0
  70. package/dist/components/formField/inputs/number/NumberInput.stories.d.ts.map +1 -0
  71. package/dist/components/formField/inputs/number/NumberInput.stories.js +22 -0
  72. package/dist/components/formField/inputs/number/NumberInput.stories.js.map +1 -0
  73. package/dist/components/formField/inputs/number/NumberInput.test.d.ts +2 -0
  74. package/dist/components/formField/inputs/number/NumberInput.test.d.ts.map +1 -0
  75. package/dist/components/formField/inputs/number/NumberInput.test.js +30 -0
  76. package/dist/components/formField/inputs/number/NumberInput.test.js.map +1 -0
  77. package/dist/components/formField/inputs/radio/RadioButtonInput.d.ts +7 -0
  78. package/dist/components/formField/inputs/radio/RadioButtonInput.d.ts.map +1 -0
  79. package/dist/components/formField/inputs/radio/RadioButtonInput.js +9 -0
  80. package/dist/components/formField/inputs/radio/RadioButtonInput.js.map +1 -0
  81. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.d.ts +46 -0
  82. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.d.ts.map +1 -0
  83. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js +83 -0
  84. package/dist/components/formField/inputs/radio/RadioButtonInput.stories.js.map +1 -0
  85. package/dist/components/formField/inputs/radio/RadioButtonInput.test.d.ts +2 -0
  86. package/dist/components/formField/inputs/radio/RadioButtonInput.test.d.ts.map +1 -0
  87. package/dist/components/formField/inputs/radio/RadioButtonInput.test.js +34 -0
  88. package/dist/components/formField/inputs/radio/RadioButtonInput.test.js.map +1 -0
  89. package/dist/components/heading/Heading.d.ts +392 -388
  90. package/dist/components/heading/Heading.d.ts.map +1 -1
  91. package/dist/components/heading/Heading.js +8 -1
  92. package/dist/components/heading/Heading.js.map +1 -1
  93. package/dist/components/heading/Heading.stories.d.ts.map +1 -1
  94. package/dist/components/heading/Heading.stories.js +7 -8
  95. package/dist/components/heading/Heading.stories.js.map +1 -1
  96. package/dist/components/heading/HeadingInnerContainer.d.ts +2 -2
  97. package/dist/components/heading/HeadingInnerContainer.js +4 -4
  98. package/dist/components/icon/Icon.d.ts +2 -2
  99. package/dist/components/icon/Icon.d.ts.map +1 -1
  100. package/dist/components/icon/Icon.js.map +1 -1
  101. package/dist/components/icon/Icon.stories.d.ts +7 -0
  102. package/dist/components/icon/Icon.stories.d.ts.map +1 -1
  103. package/dist/components/icon/Icon.stories.js +8 -0
  104. package/dist/components/icon/Icon.stories.js.map +1 -1
  105. package/dist/components/icon/allowedIcons.d.ts +1 -0
  106. package/dist/components/icon/allowedIcons.d.ts.map +1 -1
  107. package/dist/components/section/Section.d.ts +18 -0
  108. package/dist/components/section/Section.d.ts.map +1 -0
  109. package/dist/components/section/Section.js +36 -0
  110. package/dist/components/section/Section.js.map +1 -0
  111. package/dist/components/section/Section.stories.d.ts +18 -0
  112. package/dist/components/section/Section.stories.d.ts.map +1 -0
  113. package/dist/components/section/Section.stories.js +27 -0
  114. package/dist/components/section/Section.stories.js.map +1 -0
  115. package/dist/components/section/Section.test.d.ts +2 -0
  116. package/dist/components/section/Section.test.d.ts.map +1 -0
  117. package/dist/components/section/Section.test.js +157 -0
  118. package/dist/components/section/Section.test.js.map +1 -0
  119. package/dist/components/slideover/Slideover.d.ts +11 -0
  120. package/dist/components/slideover/Slideover.d.ts.map +1 -0
  121. package/dist/components/slideover/Slideover.js +11 -0
  122. package/dist/components/slideover/Slideover.js.map +1 -0
  123. package/dist/components/slideover/Slideover.test.d.ts +2 -0
  124. package/dist/components/slideover/Slideover.test.d.ts.map +1 -0
  125. package/dist/components/slideover/Slideover.test.js +33 -0
  126. package/dist/components/slideover/Slideover.test.js.map +1 -0
  127. package/dist/components/slideoverManager/SlideoverManager.d.ts +7 -0
  128. package/dist/components/slideoverManager/SlideoverManager.d.ts.map +1 -0
  129. package/dist/components/slideoverManager/SlideoverManager.js +29 -0
  130. package/dist/components/slideoverManager/SlideoverManager.js.map +1 -0
  131. package/dist/components/slideoverManager/SlideoverManager.stories.d.ts +15 -0
  132. package/dist/components/slideoverManager/SlideoverManager.stories.d.ts.map +1 -0
  133. package/dist/components/slideoverManager/SlideoverManager.stories.js +102 -0
  134. package/dist/components/slideoverManager/SlideoverManager.stories.js.map +1 -0
  135. package/dist/components/slideoverManager/SlideoverManager.test.d.ts +2 -0
  136. package/dist/components/slideoverManager/SlideoverManager.test.d.ts.map +1 -0
  137. package/dist/components/slideoverManager/SlideoverManager.test.js +53 -0
  138. package/dist/components/slideoverManager/SlideoverManager.test.js.map +1 -0
  139. package/dist/components/tabs/Tabs.d.ts +14 -18
  140. package/dist/components/tabs/Tabs.d.ts.map +1 -1
  141. package/dist/components/tabs/Tabs.js +6 -39
  142. package/dist/components/tabs/Tabs.js.map +1 -1
  143. package/dist/components/tabs/Tabs.stories.d.ts +35 -6
  144. package/dist/components/tabs/Tabs.stories.d.ts.map +1 -1
  145. package/dist/components/tabs/Tabs.stories.js +17 -45
  146. package/dist/components/tabs/Tabs.stories.js.map +1 -1
  147. package/dist/components/tabs/Tabs.test.d.ts.map +1 -1
  148. package/dist/components/tabs/Tabs.test.js +90 -97
  149. package/dist/components/tabs/Tabs.test.js.map +1 -1
  150. package/dist/components/tabs/TabsItem.d.ts +15 -0
  151. package/dist/components/tabs/TabsItem.d.ts.map +1 -0
  152. package/dist/components/tabs/TabsItem.js +18 -0
  153. package/dist/components/tabs/TabsItem.js.map +1 -0
  154. package/dist/components/tabs/TabsItem.stories.d.ts +618 -0
  155. package/dist/components/tabs/TabsItem.stories.d.ts.map +1 -0
  156. package/dist/components/tabs/TabsItem.stories.js +48 -0
  157. package/dist/components/tabs/TabsItem.stories.js.map +1 -0
  158. package/dist/index.css +1996 -1326
  159. package/dist/index.css.map +1 -1
  160. package/dist/index.d.ts +8 -1
  161. package/dist/index.d.ts.map +1 -1
  162. package/dist/index.js +8 -1
  163. package/dist/index.js.map +1 -1
  164. package/dist/utils/Constants.d.ts +6 -0
  165. package/dist/utils/Constants.d.ts.map +1 -0
  166. package/dist/utils/Constants.js +6 -0
  167. package/dist/utils/Constants.js.map +1 -0
  168. package/dist/utils/PopupParentContext.d.ts +3 -0
  169. package/dist/utils/PopupParentContext.d.ts.map +1 -0
  170. package/dist/utils/PopupParentContext.js +6 -0
  171. package/dist/utils/PopupParentContext.js.map +1 -0
  172. package/dist/utils/PubSub.d.ts +11 -0
  173. package/dist/utils/PubSub.d.ts.map +1 -0
  174. package/dist/utils/PubSub.js +27 -0
  175. package/dist/utils/PubSub.js.map +1 -0
  176. package/dist/utils/PubSub.test.d.ts +2 -0
  177. package/dist/utils/PubSub.test.d.ts.map +1 -0
  178. package/dist/utils/PubSub.test.js +229 -0
  179. package/dist/utils/PubSub.test.js.map +1 -0
  180. package/dist/utils/SlideoverUtils.d.ts +7 -0
  181. package/dist/utils/SlideoverUtils.d.ts.map +1 -0
  182. package/dist/utils/SlideoverUtils.js +8 -0
  183. package/dist/utils/SlideoverUtils.js.map +1 -0
  184. package/dist/utils/getDefaultPopupParent.d.ts +2 -0
  185. package/dist/utils/getDefaultPopupParent.d.ts.map +1 -0
  186. package/dist/utils/getDefaultPopupParent.js +13 -0
  187. package/dist/utils/getDefaultPopupParent.js.map +1 -0
  188. package/dist/utils/hooks/useComponentDidMount.d.ts +3 -0
  189. package/dist/utils/hooks/useComponentDidMount.d.ts.map +1 -0
  190. package/dist/utils/hooks/useComponentDidMount.js +5 -0
  191. package/dist/utils/hooks/useComponentDidMount.js.map +1 -0
  192. package/dist/utils/hooks/usePubSub.d.ts +2 -0
  193. package/dist/utils/hooks/usePubSub.d.ts.map +1 -0
  194. package/dist/utils/hooks/usePubSub.js +12 -0
  195. package/dist/utils/hooks/usePubSub.js.map +1 -0
  196. package/package.json +3 -3
  197. package/src/components/button/Button.story.tsx +9 -0
  198. package/src/components/button/Button.tsx +10 -2
  199. package/src/components/button/button.scss +75 -33
  200. package/src/components/card/Card.test.tsx +0 -6
  201. package/src/components/card/Card.tsx +12 -7
  202. package/src/components/card/card.scss +32 -18
  203. package/src/components/formField/FormField.stories.tsx +9 -1
  204. package/src/components/formField/FormField.test.tsx +6 -0
  205. package/src/components/formField/FormField.tsx +5 -0
  206. package/src/components/formField/formField.scss +20 -8
  207. package/src/components/formField/inputs/checkbox/CheckboxInput.stories.tsx +22 -0
  208. package/src/components/formField/inputs/checkbox/CheckboxInput.test.tsx +35 -0
  209. package/src/components/formField/inputs/checkbox/CheckboxInput.tsx +79 -0
  210. package/src/components/formField/inputs/checkbox/checkboxInput.scss +96 -0
  211. package/src/components/formField/inputs/dropdown/Dropdown.stories.tsx +185 -0
  212. package/src/components/formField/inputs/dropdown/Dropdown.test.tsx +185 -0
  213. package/src/components/formField/inputs/dropdown/Dropdown.tsx +82 -0
  214. package/src/components/formField/inputs/dropdown/buttons/dropdownButton/DropdownButton.tsx +41 -0
  215. package/src/components/formField/inputs/dropdown/buttons/dropdownButton/dropdownButton.scss +12 -0
  216. package/src/components/formField/inputs/dropdown/dropdown.scss +24 -0
  217. package/src/components/formField/inputs/dropdown/items/DropdownItemRenderer.tsx +38 -0
  218. package/src/components/formField/inputs/dropdown/items/dropdownItem/DropdownItem.tsx +49 -0
  219. package/src/components/formField/inputs/dropdown/items/dropdownItem/dropdownItem.scss +62 -0
  220. package/src/components/formField/inputs/dropdown/items/dropdownMultiLineItem/DropdownMultiLineItem.tsx +48 -0
  221. package/src/components/formField/inputs/dropdown/items/dropdownMultiLineItem/dropdownMultiLineItem.scss +52 -0
  222. package/src/components/formField/inputs/dropdown/wrapper/DropdownWrapper.tsx +138 -0
  223. package/src/components/formField/inputs/dropdown/wrapper/dropdownWrapper.scss +32 -0
  224. package/src/components/formField/inputs/input.scss +25 -26
  225. package/src/components/formField/inputs/number/NumberInput.stories.tsx +25 -0
  226. package/src/components/formField/inputs/number/NumberInput.test.tsx +33 -0
  227. package/src/components/formField/inputs/number/NumberInput.tsx +107 -0
  228. package/src/components/formField/inputs/number/numberInput.scss +68 -0
  229. package/src/components/formField/inputs/radio/RadioButtonInput.stories.tsx +97 -0
  230. package/src/components/formField/inputs/radio/RadioButtonInput.test.tsx +37 -0
  231. package/src/components/formField/inputs/radio/RadioButtonInput.tsx +46 -0
  232. package/src/components/formField/inputs/radio/radioButtonInput.scss +100 -0
  233. package/src/components/formField/label/label.scss +5 -1
  234. package/src/components/heading/Heading.stories.tsx +11 -12
  235. package/src/components/heading/Heading.tsx +21 -2
  236. package/src/components/heading/heading.scss +4 -0
  237. package/src/components/icon/Icon.stories.tsx +8 -0
  238. package/src/components/icon/Icon.tsx +2 -2
  239. package/src/components/icon/allowedIcons.tsx +2 -0
  240. package/src/components/pill/pill.scss +7 -7
  241. package/src/components/section/Section.stories.tsx +34 -0
  242. package/src/components/section/Section.test.tsx +308 -0
  243. package/src/components/section/Section.tsx +131 -0
  244. package/src/components/section/section.scss +42 -0
  245. package/src/components/slideover/Slideover.test.tsx +36 -0
  246. package/src/components/slideover/Slideover.tsx +38 -0
  247. package/src/components/slideover/slideover.scss +50 -0
  248. package/src/components/slideoverManager/SlideoverManager.stories.tsx +374 -0
  249. package/src/components/slideoverManager/SlideoverManager.test.tsx +64 -0
  250. package/src/components/slideoverManager/SlideoverManager.tsx +51 -0
  251. package/src/components/slideoverManager/slideoverManager.scss +13 -0
  252. package/src/components/tabs/Tabs.stories.tsx +92 -0
  253. package/src/components/tabs/Tabs.test.tsx +220 -0
  254. package/src/components/tabs/Tabs.tsx +14 -0
  255. package/src/components/tabs/TabsItem.stories.tsx +55 -0
  256. package/src/components/tabs/TabsItem.tsx +42 -0
  257. package/src/components/tabs/tabs.scss +62 -0
  258. package/src/global.scss +10 -1
  259. package/src/index.scss +15 -3
  260. package/src/index.ts +10 -3
  261. package/src/tokens.scss +1321 -1238
  262. package/src/utils/Constants.ts +5 -0
  263. package/src/utils/PopupParentContext.ts +6 -0
  264. package/src/utils/PubSub.test.ts +303 -0
  265. package/src/utils/PubSub.ts +34 -0
  266. package/src/utils/SlideoverUtils.ts +9 -0
  267. package/src/utils/getDefaultPopupParent.ts +14 -0
  268. package/src/utils/hooks/useComponentDidMount.ts +5 -0
  269. package/src/utils/hooks/usePubSub.ts +12 -0
  270. package/tokens/export-config.json +32 -0
  271. package/tokens/json/$metadata.json +5 -0
  272. package/tokens/json/$themes.json +1333 -0
  273. package/tokens/json/Arbor.json +6329 -0
  274. package/src/components/heading/HeadingInnerContainer.tsx +0 -18
@@ -0,0 +1,374 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { SlideoverManager } from './SlideoverManager';
3
+ import { SlideoverUtils } from '../../utils/SlideoverUtils';
4
+ import { Button } from '../button/Button';
5
+ import { Section } from '../section/Section';
6
+ import { FormField } from '../formField/FormField';
7
+ import { generateUuid } from '../../utils/generateUuid';
8
+ import { allowedIcons, type IconName } from '../icon/allowedIcons';
9
+
10
+ type SlideoverStoryArgs = {
11
+ headerIcon?: IconName;
12
+ centerHeaderText?: boolean;
13
+ };
14
+
15
+ const meta: Meta<SlideoverStoryArgs> = {
16
+ title: 'Components/SlideoverManager',
17
+ parameters: {
18
+ layout: 'fullscreen',
19
+ },
20
+ argTypes: {
21
+ headerIcon: {
22
+ control: { type: 'select' },
23
+ options: Object.keys(allowedIcons),
24
+ description: 'Icon to display in the slideover header',
25
+ },
26
+ centerHeaderText: {
27
+ control: { type: 'boolean' },
28
+ description: 'Whether to center the header text',
29
+ },
30
+ },
31
+ args: {
32
+ centerHeaderText: true,
33
+ },
34
+ decorators: [
35
+ Story => (
36
+ <div>
37
+ <Story />
38
+ <div style={{ padding: '1rem' }}>
39
+ <p>
40
+ The SlideoverManager is a container that manages the display of slideovers. It listens for events to add or remove slideovers.
41
+ </p>
42
+ <p>
43
+ Use the buttons below to add slideovers with different content.
44
+ </p>
45
+ </div>
46
+ </div>
47
+ ),
48
+ ],
49
+ };
50
+
51
+ export default meta;
52
+
53
+ type Story = StoryObj<SlideoverStoryArgs>;
54
+
55
+ let slideoverCount = 0;
56
+
57
+ const addSlideoverWithContent = (content: React.ReactNode, headerIcon?: IconName, centerHeaderText?: boolean) => {
58
+ slideoverCount++;
59
+ SlideoverUtils.addSlideover({
60
+ title: `Slideover ${slideoverCount}`,
61
+ children: content,
62
+ headerIcon,
63
+ centerHeaderText,
64
+ });
65
+ };
66
+
67
+ const removeSlideover = () => {
68
+ if (slideoverCount > 0) {
69
+ slideoverCount--;
70
+ }
71
+ SlideoverUtils.removeSlideover();
72
+ };
73
+
74
+ const removeAllSlideovers = () => {
75
+ slideoverCount = 0;
76
+ SlideoverUtils.removeAllSlideovers();
77
+ };
78
+
79
+ export const Default: Story = {
80
+ render: args => (
81
+ <>
82
+ <SlideoverManager slideovers={[]} />
83
+ <div style={{ padding: '1rem', display: 'flex', gap: '1rem' }}>
84
+ <Button
85
+ onClick={() =>
86
+ addSlideoverWithContent(<p>This is a simple slideover.</p>, args.headerIcon, args.centerHeaderText)}
87
+ >
88
+ Add Simple Slideover
89
+ </Button>
90
+ <Button onClick={removeSlideover} type="secondary">
91
+ Remove Last Slideover
92
+ </Button>
93
+ <Button onClick={removeAllSlideovers} type="primary-destructive">
94
+ Remove All
95
+ </Button>
96
+ </div>
97
+ </>
98
+ ),
99
+ };
100
+
101
+ export const WithSections: Story = {
102
+ render: args => (
103
+ <>
104
+ <SlideoverManager slideovers={[]} />
105
+ <div style={{ padding: '1rem', display: 'flex', gap: '1rem' }}>
106
+ <Button
107
+ onClick={() =>
108
+ addSlideoverWithContent(
109
+ <>
110
+ <Section title="Section 1" collapsible>
111
+ <p>Aliquip ea tempor officia irure do qui culpa. Laborum proident laboris aliqua ad Lorem eiusmod fugiat dolore qui occaecat adipisicing. Dolore quis nisi occaecat commodo labore ad nulla aliquip in. Enim labore nisi laborum nostrud officia ad nulla ut quis. Aute excepteur quis amet aliquip. Excepteur Lorem cupidatat adipisicing consectetur ipsum Lorem. Deserunt dolor veniam sit mollit elit aliquip duis.</p>
112
+ </Section>
113
+ <Section title="Section 2" collapsible collapsed>
114
+ <p>Veniam adipisicing culpa id esse duis in officia consequat veniam ad ullamco sint sunt anim. Incididunt exercitation dolor Lorem anim aute ad deserunt. Nulla culpa sint aliqua ea Lorem sint. Elit sit consectetur minim cillum consectetur pariatur Lorem labore consectetur nisi consectetur officia exercitation. Est consectetur commodo deserunt ipsum aliqua occaecat qui sunt consectetur.</p>
115
+ </Section>
116
+ </>,
117
+ args.headerIcon,
118
+ args.centerHeaderText,
119
+ )}
120
+ >
121
+ Add Slideover with Sections
122
+ </Button>
123
+ <Button onClick={removeSlideover} type="secondary">
124
+ Remove Last Slideover
125
+ </Button>
126
+ <Button onClick={removeAllSlideovers} type="primary-destructive">
127
+ Remove All
128
+ </Button>
129
+ </div>
130
+ </>
131
+ ),
132
+ };
133
+
134
+ export const WithFormFields: Story = {
135
+ render: (args) => {
136
+ const formFieldId = generateUuid();
137
+ return (
138
+ <>
139
+ <SlideoverManager slideovers={[]} />
140
+ <div style={{ padding: '1rem', display: 'flex', gap: '1rem' }}>
141
+ <Button
142
+ onClick={() =>
143
+ addSlideoverWithContent(
144
+ <>
145
+ <FormField
146
+ id={formFieldId}
147
+ label="Your Name"
148
+ inputType="text"
149
+ inputProps={{ placeholder: 'e.g. Jane Doe' }}
150
+ fieldDescription="Please enter your full name."
151
+ />
152
+ </>,
153
+ args.headerIcon,
154
+ args.centerHeaderText,
155
+ )}
156
+ >
157
+ Add Slideover with Form
158
+ </Button>
159
+ <Button onClick={removeSlideover} type="secondary">
160
+ Remove Last Slideover
161
+ </Button>
162
+ <Button onClick={removeAllSlideovers} type="primary-destructive">
163
+ Remove All
164
+ </Button>
165
+ </div>
166
+ </>
167
+ );
168
+ },
169
+ };
170
+
171
+ export const WithFooterContent: Story = {
172
+ render: (args) => {
173
+ const handleSave = () => {
174
+ alert('Save clicked!');
175
+ SlideoverUtils.removeSlideover();
176
+ };
177
+
178
+ const handleCancel = () => {
179
+ SlideoverUtils.removeSlideover();
180
+ };
181
+
182
+ const footerContent = (
183
+ <div style={{ display: 'flex', gap: '1rem', justifyContent: 'flex-end' }}>
184
+ <Button type="secondary" onClick={handleCancel}>
185
+ Cancel
186
+ </Button>
187
+ <Button type="primary" onClick={handleSave}>
188
+ Save Changes
189
+ </Button>
190
+ </div>
191
+ );
192
+
193
+ return (
194
+ <>
195
+ <SlideoverManager slideovers={[]} />
196
+ <div style={{ padding: '1rem', display: 'flex', gap: '1rem' }}>
197
+ <Button
198
+ onClick={() => {
199
+ slideoverCount++;
200
+ SlideoverUtils.addSlideover({
201
+ title: `Slideover ${slideoverCount}`,
202
+ children: (
203
+ <>
204
+ <Section title="Edit Settings">
205
+ <FormField
206
+ id={generateUuid()}
207
+ label="Setting Name"
208
+ inputType="text"
209
+ inputProps={{ placeholder: 'Enter setting name' }}
210
+ />
211
+ <FormField
212
+ id={generateUuid()}
213
+ label="Description"
214
+ inputType="textarea"
215
+ inputProps={{ placeholder: 'Enter description', rows: 4 }}
216
+ />
217
+ </Section>
218
+ </>
219
+ ),
220
+ footerContents: footerContent,
221
+ headerIcon: args.headerIcon,
222
+ centerHeaderText: args.centerHeaderText,
223
+ });
224
+ }}
225
+ >
226
+ Add Slideover with Footer
227
+ </Button>
228
+ <Button onClick={removeSlideover} type="secondary">
229
+ Remove Last Slideover
230
+ </Button>
231
+ <Button onClick={removeAllSlideovers} type="primary-destructive">
232
+ Remove All
233
+ </Button>
234
+ </div>
235
+ </>
236
+ );
237
+ },
238
+ };
239
+
240
+ export const WithScrollableContent: Story = {
241
+ render: (args) => {
242
+ const footerContent = (
243
+ <div style={{ display: 'flex', gap: '1rem', justifyContent: 'flex-end' }}>
244
+ <Button type="secondary" onClick={SlideoverUtils.removeSlideover}>
245
+ Cancel
246
+ </Button>
247
+ <Button type="primary" onClick={SlideoverUtils.removeSlideover}>
248
+ Save
249
+ </Button>
250
+ </div>
251
+ );
252
+
253
+ return (
254
+ <>
255
+ <SlideoverManager slideovers={[]} />
256
+ <div style={{ padding: '1rem', display: 'flex', gap: '1rem' }}>
257
+ <Button
258
+ onClick={() => {
259
+ slideoverCount++;
260
+ SlideoverUtils.addSlideover({
261
+ title: `Slideover ${slideoverCount}`,
262
+ children: (
263
+ <>
264
+ <Section title="Section 1" collapsible>
265
+ <p>
266
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
267
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
268
+ </p>
269
+ <FormField
270
+ id={generateUuid()}
271
+ label="Field 1"
272
+ inputType="text"
273
+ inputProps={{ placeholder: 'Enter value' }}
274
+ />
275
+ <FormField
276
+ id={generateUuid()}
277
+ label="Field 2"
278
+ inputType="text"
279
+ inputProps={{ placeholder: 'Enter value' }}
280
+ />
281
+ </Section>
282
+ <Section title="Section 2" collapsible>
283
+ <p>
284
+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
285
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
286
+ </p>
287
+ <FormField
288
+ id={generateUuid()}
289
+ label="Field 3"
290
+ inputType="textarea"
291
+ inputProps={{ placeholder: 'Enter long text', rows: 6 }}
292
+ />
293
+ </Section>
294
+ <Section title="Section 3" collapsible>
295
+ <p>
296
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium,
297
+ totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
298
+ </p>
299
+ <FormField
300
+ id={generateUuid()}
301
+ label="Field 4"
302
+ inputType="number"
303
+ inputProps={{ placeholder: 'Enter number' }}
304
+ />
305
+ <FormField
306
+ id={generateUuid()}
307
+ label="Field 5"
308
+ inputType="text"
309
+ inputProps={{ placeholder: 'Enter value' }}
310
+ />
311
+ </Section>
312
+ <Section title="Section 4" collapsible>
313
+ <p>
314
+ Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores
315
+ eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet.
316
+ </p>
317
+ <FormField
318
+ id={generateUuid()}
319
+ label="Field 6"
320
+ inputType="text"
321
+ inputProps={{ placeholder: 'Enter value' }}
322
+ />
323
+ </Section>
324
+ <Section title="Section 5" collapsible>
325
+ <p>
326
+ At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque
327
+ corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.
328
+ </p>
329
+ <FormField
330
+ id={generateUuid()}
331
+ label="Field 7"
332
+ inputType="textarea"
333
+ inputProps={{ placeholder: 'Enter description', rows: 4 }}
334
+ />
335
+ <FormField
336
+ id={generateUuid()}
337
+ label="Field 8"
338
+ inputType="text"
339
+ inputProps={{ placeholder: 'Enter value' }}
340
+ />
341
+ </Section>
342
+ <Section title="Section 6" collapsible collapsed>
343
+ <p>
344
+ Similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.
345
+ Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio.
346
+ </p>
347
+ <FormField
348
+ id={generateUuid()}
349
+ label="Field 9"
350
+ inputType="text"
351
+ inputProps={{ placeholder: 'Enter value' }}
352
+ />
353
+ </Section>
354
+ </>
355
+ ),
356
+ footerContents: footerContent,
357
+ headerIcon: args.headerIcon,
358
+ centerHeaderText: args.centerHeaderText,
359
+ });
360
+ }}
361
+ >
362
+ Add Slideover with Scrollable Content
363
+ </Button>
364
+ <Button onClick={removeSlideover} type="secondary">
365
+ Remove Last Slideover
366
+ </Button>
367
+ <Button onClick={removeAllSlideovers} type="primary-destructive">
368
+ Remove All
369
+ </Button>
370
+ </div>
371
+ </>
372
+ );
373
+ },
374
+ };
@@ -0,0 +1,64 @@
1
+ import { expect, test, describe } from 'vitest';
2
+ import { render, screen, act } from '@testing-library/react';
3
+ import { SlideoverManager } from './SlideoverManager';
4
+ import '@testing-library/jest-dom/vitest';
5
+ import { SlideoverUtils } from 'Utils/SlideoverUtils';
6
+ import type { SlideoverProps } from 'Components/slideover/Slideover';
7
+
8
+ const slideover1: SlideoverProps = {
9
+ title: 'Slideover 1',
10
+ children: 'Content 1',
11
+ };
12
+
13
+ const slideover2: SlideoverProps = {
14
+ title: 'Slideover 2',
15
+ children: 'Content 2',
16
+ };
17
+
18
+ describe('SlideoverManager', () => {
19
+ test('updates slideovers when the slideovers prop changes', () => {
20
+ const { rerender } = render(<SlideoverManager slideovers={[]} />);
21
+ expect(screen.queryByText('Slideover 1')).not.toBeInTheDocument();
22
+
23
+ rerender(<SlideoverManager slideovers={[slideover1]} />);
24
+ expect(screen.getByText('Slideover 1')).toBeInTheDocument();
25
+
26
+ rerender(<SlideoverManager slideovers={[slideover1, slideover2]} />);
27
+ expect(screen.getByText('Slideover 1')).toBeInTheDocument();
28
+ expect(screen.getByText('Slideover 2')).toBeInTheDocument();
29
+
30
+ rerender(<SlideoverManager slideovers={[slideover2]} />);
31
+ expect(screen.queryByText('Slideover 1')).not.toBeInTheDocument();
32
+ expect(screen.getByText('Slideover 2')).toBeInTheDocument();
33
+
34
+ rerender(<SlideoverManager slideovers={[]} />);
35
+ expect(screen.queryByText('Slideover 1')).not.toBeInTheDocument();
36
+ expect(screen.queryByText('Slideover 2')).not.toBeInTheDocument();
37
+ });
38
+
39
+ test('adds and removes slideovers using SlideoverUtils', () => {
40
+ render(<SlideoverManager slideovers={[]} />);
41
+
42
+ act(() => {
43
+ SlideoverUtils.addSlideover({ title: 'First Slideover', children: '' });
44
+ });
45
+ expect(screen.getByText('First Slideover')).toBeInTheDocument();
46
+
47
+ act(() => {
48
+ SlideoverUtils.addSlideover({ title: 'Second Slideover', children: '' });
49
+ });
50
+ expect(screen.getByText('First Slideover')).toBeInTheDocument();
51
+ expect(screen.getByText('Second Slideover')).toBeInTheDocument();
52
+
53
+ act(() => {
54
+ SlideoverUtils.removeSlideover();
55
+ });
56
+ expect(screen.getByText('First Slideover')).toBeInTheDocument();
57
+ expect(screen.queryByText('Second Slideover')).not.toBeInTheDocument();
58
+
59
+ act(() => {
60
+ SlideoverUtils.removeAllSlideovers();
61
+ });
62
+ expect(screen.queryByText('First Slideover')).not.toBeInTheDocument();
63
+ });
64
+ });
@@ -0,0 +1,51 @@
1
+ import classNames from 'classnames';
2
+ import { Slideover, type SlideoverProps } from 'Components/slideover/Slideover';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { SLIDEOVER } from 'Utils/Constants';
5
+ import { usePubSub } from 'Utils/hooks/usePubSub';
6
+ import { PopupParentContext } from 'Utils/PopupParentContext';
7
+
8
+ type SlideoverManagerProps = {
9
+ slideovers: SlideoverProps[];
10
+ };
11
+
12
+ export const SlideoverManager = (props: SlideoverManagerProps) => {
13
+ const { slideovers: initialSlideovers } = props;
14
+ const [slideovers, setSlideovers] = useState(() => initialSlideovers);
15
+
16
+ const popupParentContainerRef = useRef<HTMLDivElement | null>(null);
17
+
18
+ useEffect(() => {
19
+ setSlideovers(initialSlideovers);
20
+ }, [initialSlideovers]);
21
+
22
+ const hasSlideovers = slideovers.length > 0;
23
+
24
+ usePubSub(SLIDEOVER.ADD_SLIDEOVER, (slideover: SlideoverProps) => {
25
+ setSlideovers(currentSlideovers => [...currentSlideovers, slideover]);
26
+ });
27
+
28
+ usePubSub(SLIDEOVER.REMOVE_SLIDEOVER, () => {
29
+ setSlideovers(currentSlideovers => currentSlideovers.slice(0, currentSlideovers.length - 1));
30
+ });
31
+
32
+ usePubSub(SLIDEOVER.REMOVE_ALL_SLIDEOVERS, () => {
33
+ setSlideovers([]);
34
+ });
35
+
36
+ return (
37
+ <PopupParentContext.Provider value={popupParentContainerRef}>
38
+ <div
39
+ className={classNames(
40
+ 'ds-slideover-manager',
41
+ {
42
+ 'ds-slideover-manager--active': hasSlideovers,
43
+ },
44
+ )}
45
+ ref={popupParentContainerRef}
46
+ >
47
+ {slideovers.map((slideoverProps, index) => <Slideover key={index} {...slideoverProps} />)}
48
+ </div>
49
+ </PopupParentContext.Provider>
50
+ );
51
+ };
@@ -0,0 +1,13 @@
1
+ .ds-slideover-manager {
2
+ display: none;
3
+
4
+ &--active {
5
+ display: block;
6
+ position: fixed;
7
+ top: 0;
8
+ left: 0;
9
+ background-color: var(--slideover-overlay-color-background);
10
+ height: 100vh;
11
+ width: 100vw;
12
+ }
13
+ }
@@ -0,0 +1,92 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Tabs } from './Tabs';
3
+
4
+ const meta = {
5
+ title: 'Components/Tabs',
6
+ component: Tabs,
7
+ parameters: {
8
+ layout: 'padded',
9
+ },
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ children: {
13
+ control: false,
14
+ description: 'Tab items to display',
15
+ },
16
+ className: {
17
+ control: 'text',
18
+ description: 'Additional CSS classes',
19
+ },
20
+ },
21
+ } satisfies Meta<typeof Tabs>;
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof meta>;
25
+
26
+ // Basic tabs with buttons
27
+ export const Default: Story = {
28
+ args: {
29
+ children: (
30
+ <>
31
+ <Tabs.Item active>Overview</Tabs.Item>
32
+ <Tabs.Item>Details</Tabs.Item>
33
+ <Tabs.Item>Settings</Tabs.Item>
34
+ </>
35
+ ),
36
+ },
37
+ };
38
+
39
+ // Tabs with links
40
+ export const WithLinks: Story = {
41
+ args: {
42
+ children: (
43
+ <>
44
+ <Tabs.Item tabElement="link" tabElementProps={{ href: '#overview' }} active>
45
+ Overview
46
+ </Tabs.Item>
47
+ <Tabs.Item tabElement="link" tabElementProps={{ href: '#details' }}>
48
+ Details
49
+ </Tabs.Item>
50
+ <Tabs.Item tabElement="link" tabElementProps={{ href: '#settings' }}>
51
+ Settings
52
+ </Tabs.Item>
53
+ </>
54
+ ),
55
+ },
56
+ };
57
+
58
+ // Mixed tabs (buttons and links)
59
+ export const Mixed: Story = {
60
+ args: {
61
+ children: (
62
+ <>
63
+ <Tabs.Item active>Home</Tabs.Item>
64
+ <Tabs.Item tabElement="link" tabElementProps={{ href: '#about' }}>
65
+ About
66
+ </Tabs.Item>
67
+ <Tabs.Item>Contact</Tabs.Item>
68
+ <Tabs.Item tabElement="link" tabElementProps={{ href: '#help' }}>
69
+ Help
70
+ </Tabs.Item>
71
+ </>
72
+ ),
73
+ },
74
+ };
75
+
76
+ // Many tabs
77
+ export const ManyTabs: Story = {
78
+ args: {
79
+ children: (
80
+ <>
81
+ <Tabs.Item active iconName="list">Tab 1</Tabs.Item>
82
+ <Tabs.Item iconName="list">Tab 2</Tabs.Item>
83
+ <Tabs.Item iconName="list">Tab 3</Tabs.Item>
84
+ <Tabs.Item iconName="list">Tab 4</Tabs.Item>
85
+ <Tabs.Item iconName="list">Tab 5</Tabs.Item>
86
+ <Tabs.Item iconName="list">Tab 6</Tabs.Item>
87
+ <Tabs.Item iconName="list">Tab 7</Tabs.Item>
88
+ <Tabs.Item iconName="list">Tab 8</Tabs.Item>
89
+ </>
90
+ ),
91
+ },
92
+ };