@goodhood-web/ui 0.0.3 → 0.0.4

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 (291) hide show
  1. package/.babelrc +12 -0
  2. package/.eslintrc.json +25 -0
  3. package/.storybook/main.ts +31 -0
  4. package/.storybook/manager-head.html +1 -0
  5. package/.storybook/manager.ts +7 -0
  6. package/.storybook/nebenanTheme.ts +17 -0
  7. package/.storybook/preview.ts +9 -0
  8. package/.stylelintrc.json +14 -0
  9. package/README.md +7 -0
  10. package/__mocks__/svg.js +2 -0
  11. package/images/favicon.ico +0 -0
  12. package/images/logo.svg +11 -0
  13. package/jest.config.ts +16 -0
  14. package/package.json +1 -1
  15. package/project.json +88 -0
  16. package/{index.d.ts → src/index.ts} +25 -1
  17. package/src/lib/BaseButton/BaseButton.module.scss +11 -0
  18. package/src/lib/BaseButton/BaseButton.spec.tsx +12 -0
  19. package/src/lib/BaseButton/BaseButton.stories.tsx +26 -0
  20. package/src/lib/BaseButton/BaseButton.tsx +39 -0
  21. package/src/lib/Card/Card.module.scss +15 -0
  22. package/src/lib/Card/Card.spec.tsx +15 -0
  23. package/src/lib/Card/Card.stories.tsx +159 -0
  24. package/src/lib/Card/Card.tsx +31 -0
  25. package/src/lib/Card/Card.types.ts +12 -0
  26. package/src/lib/Card/Card.utils.spec.tsx +51 -0
  27. package/src/lib/Card/Card.utils.ts +23 -0
  28. package/src/lib/Card/CardBody/CardBody.module.scss +4 -0
  29. package/src/lib/Card/CardBody/CardBody.spec.tsx +15 -0
  30. package/src/lib/Card/CardBody/CardBody.stories.tsx +108 -0
  31. package/src/lib/Card/CardBody/CardBody.tsx +9 -0
  32. package/src/lib/Card/CardBody/CardBody.types.ts +4 -0
  33. package/src/lib/Card/CardHeader/CardHeader.module.scss +12 -0
  34. package/src/lib/Card/CardHeader/CardHeader.spec.tsx +72 -0
  35. package/src/lib/Card/CardHeader/CardHeader.stories.tsx +77 -0
  36. package/src/lib/Card/CardHeader/CardHeader.tsx +29 -0
  37. package/src/lib/Card/CardHeader/CardHeader.type.ts +14 -0
  38. package/src/lib/ContentCreatorButton/ContentCreatorButton.module.scss +13 -0
  39. package/src/lib/ContentCreatorButton/ContentCreatorButton.spec.tsx +14 -0
  40. package/src/lib/ContentCreatorButton/ContentCreatorButton.stories.tsx +29 -0
  41. package/src/lib/ContentCreatorButton/ContentCreatorButton.tsx +35 -0
  42. package/{lib/ContentCreatorButton/ContentCreatorButton.types.d.ts → src/lib/ContentCreatorButton/ContentCreatorButton.types.ts} +3 -2
  43. package/src/lib/Divider/Divider.module.scss +10 -0
  44. package/src/lib/Divider/Divider.spec.tsx +46 -0
  45. package/src/lib/Divider/Divider.stories.tsx +35 -0
  46. package/src/lib/Divider/Divider.tsx +17 -0
  47. package/src/lib/Divider/Divider.types.ts +6 -0
  48. package/src/lib/Fieldset/Fieldset.module.scss +3 -0
  49. package/src/lib/Fieldset/Fieldset.spec.tsx +68 -0
  50. package/src/lib/Fieldset/Fieldset.stories.tsx +60 -0
  51. package/src/lib/Fieldset/Fieldset.tsx +28 -0
  52. package/src/lib/Fieldset/Fieldset.types.ts +7 -0
  53. package/src/lib/Form/Form.spec.tsx +15 -0
  54. package/src/lib/Form/Form.stories.tsx +53 -0
  55. package/src/lib/Form/Form.tsx +14 -0
  56. package/src/lib/Form/Form.types.ts +11 -0
  57. package/src/lib/Icon/Icon.module.scss +7 -0
  58. package/src/lib/Icon/Icon.spec.tsx +28 -0
  59. package/src/lib/Icon/Icon.stories.tsx +88 -0
  60. package/src/lib/Icon/Icon.tsx +29 -0
  61. package/src/lib/Icon/Icon.types.ts +23 -0
  62. package/src/lib/Icon/icons/24x24/index.ts +89 -0
  63. package/src/lib/Icon/icons/24x24/svg/arrow_left.svg +1 -0
  64. package/src/lib/Icon/icons/24x24/svg/arrow_right.svg +1 -0
  65. package/src/lib/Icon/icons/24x24/svg/bookmark.svg +1 -0
  66. package/src/lib/Icon/icons/24x24/svg/bookmarked.svg +1 -0
  67. package/src/lib/Icon/icons/24x24/svg/burger_menu.svg +1 -0
  68. package/src/lib/Icon/icons/24x24/svg/camera.svg +1 -0
  69. package/src/lib/Icon/icons/24x24/svg/checkmark.svg +1 -0
  70. package/src/lib/Icon/icons/24x24/svg/checkmark_circle.svg +1 -0
  71. package/src/lib/Icon/icons/24x24/svg/chevron_down.svg +1 -0
  72. package/src/lib/Icon/icons/24x24/svg/chevron_left.svg +1 -0
  73. package/src/lib/Icon/icons/24x24/svg/chevron_right.svg +1 -0
  74. package/src/lib/Icon/icons/24x24/svg/chevron_up.svg +1 -0
  75. package/src/lib/Icon/icons/24x24/svg/comment_bubble.svg +1 -0
  76. package/src/lib/Icon/icons/24x24/svg/cross.svg +1 -0
  77. package/src/lib/Icon/icons/24x24/svg/cross_circle.svg +1 -0
  78. package/src/lib/Icon/icons/24x24/svg/envelope.svg +1 -0
  79. package/src/lib/Icon/icons/24x24/svg/event_calendar.svg +1 -0
  80. package/src/lib/Icon/icons/24x24/svg/external_link.svg +1 -0
  81. package/src/lib/Icon/icons/24x24/svg/eye.svg +1 -0
  82. package/src/lib/Icon/icons/24x24/svg/eye_crossed.svg +1 -0
  83. package/src/lib/Icon/icons/24x24/svg/filter.svg +1 -0
  84. package/src/lib/Icon/icons/24x24/svg/globe.svg +1 -0
  85. package/src/lib/Icon/icons/24x24/svg/heart.svg +1 -0
  86. package/src/lib/Icon/icons/24x24/svg/image.svg +1 -0
  87. package/src/lib/Icon/icons/24x24/svg/loudspeaker.svg +1 -0
  88. package/src/lib/Icon/icons/24x24/svg/marketplace.svg +1 -0
  89. package/src/lib/Icon/icons/24x24/svg/more_dots.svg +1 -0
  90. package/src/lib/Icon/icons/24x24/svg/more_dots_alt.svg +1 -0
  91. package/src/lib/Icon/icons/24x24/svg/mute.svg +1 -0
  92. package/src/lib/Icon/icons/24x24/svg/notification_bell.svg +1 -0
  93. package/src/lib/Icon/icons/24x24/svg/paperclip.svg +1 -0
  94. package/src/lib/Icon/icons/24x24/svg/pencil.svg +1 -0
  95. package/src/lib/Icon/icons/24x24/svg/pin.svg +1 -0
  96. package/src/lib/Icon/icons/24x24/svg/plus.svg +1 -0
  97. package/src/lib/Icon/icons/24x24/svg/plus_circle.svg +1 -0
  98. package/src/lib/Icon/icons/24x24/svg/privacy_lock.svg +1 -0
  99. package/src/lib/Icon/icons/24x24/svg/search.svg +1 -0
  100. package/src/lib/Icon/icons/24x24/svg/share_arrow.svg +1 -0
  101. package/src/lib/Icon/icons/24x24/svg/share_arrow_outline.svg +1 -0
  102. package/src/lib/Icon/icons/24x24/svg/sort.svg +1 -0
  103. package/src/lib/Icon/icons/24x24/svg/thanks.svg +1 -0
  104. package/src/lib/Icon/icons/24x24/svg/trash_can.svg +1 -0
  105. package/src/lib/Icon/icons/32x32/index.ts +179 -0
  106. package/src/lib/Icon/icons/32x32/svg/address_book.svg +1 -0
  107. package/src/lib/Icon/icons/32x32/svg/baby_toy.svg +1 -0
  108. package/src/lib/Icon/icons/32x32/svg/bicycle.svg +1 -0
  109. package/src/lib/Icon/icons/32x32/svg/bookmark.svg +1 -0
  110. package/src/lib/Icon/icons/32x32/svg/books.svg +1 -0
  111. package/src/lib/Icon/icons/32x32/svg/bubble_heart_filled.svg +1 -0
  112. package/src/lib/Icon/icons/32x32/svg/bubble_heart_outline.svg +1 -0
  113. package/src/lib/Icon/icons/32x32/svg/buildings.svg +1 -0
  114. package/src/lib/Icon/icons/32x32/svg/burger_menu.svg +1 -0
  115. package/src/lib/Icon/icons/32x32/svg/business.svg +1 -0
  116. package/src/lib/Icon/icons/32x32/svg/business_profile.svg +1 -0
  117. package/src/lib/Icon/icons/32x32/svg/camera.svg +1 -0
  118. package/src/lib/Icon/icons/32x32/svg/camera_crossed.svg +1 -0
  119. package/src/lib/Icon/icons/32x32/svg/car.svg +1 -0
  120. package/src/lib/Icon/icons/32x32/svg/carrot.svg +1 -0
  121. package/src/lib/Icon/icons/32x32/svg/chat.svg +1 -0
  122. package/src/lib/Icon/icons/32x32/svg/checkmark_circle.svg +1 -0
  123. package/src/lib/Icon/icons/32x32/svg/christmas_tree.svg +1 -0
  124. package/src/lib/Icon/icons/32x32/svg/clipboard.svg +1 -0
  125. package/src/lib/Icon/icons/32x32/svg/clothing.svg +1 -0
  126. package/src/lib/Icon/icons/32x32/svg/cocktail.svg +1 -0
  127. package/src/lib/Icon/icons/32x32/svg/comment_bubble.svg +1 -0
  128. package/src/lib/Icon/icons/32x32/svg/compass.svg +1 -0
  129. package/src/lib/Icon/icons/32x32/svg/computer.svg +1 -0
  130. package/src/lib/Icon/icons/32x32/svg/couch.svg +1 -0
  131. package/src/lib/Icon/icons/32x32/svg/credit_card.svg +1 -0
  132. package/src/lib/Icon/icons/32x32/svg/cross_circle.svg +1 -0
  133. package/src/lib/Icon/icons/32x32/svg/cutlery.svg +1 -0
  134. package/src/lib/Icon/icons/32x32/svg/drill_tool.svg +1 -0
  135. package/src/lib/Icon/icons/32x32/svg/email.svg +1 -0
  136. package/src/lib/Icon/icons/32x32/svg/envelope.svg +1 -0
  137. package/src/lib/Icon/icons/32x32/svg/event_calendar_check.svg +1 -0
  138. package/src/lib/Icon/icons/32x32/svg/event_calendar_date.svg +1 -0
  139. package/src/lib/Icon/icons/32x32/svg/event_calendar_plus.svg +1 -0
  140. package/src/lib/Icon/icons/32x32/svg/exchange.svg +1 -0
  141. package/src/lib/Icon/icons/32x32/svg/eye.svg +1 -0
  142. package/src/lib/Icon/icons/32x32/svg/eye_crossed.svg +1 -0
  143. package/src/lib/Icon/icons/32x32/svg/gift.svg +1 -0
  144. package/src/lib/Icon/icons/32x32/svg/group.svg +1 -0
  145. package/src/lib/Icon/icons/32x32/svg/healthcare.svg +1 -0
  146. package/src/lib/Icon/icons/32x32/svg/heart.svg +1 -0
  147. package/src/lib/Icon/icons/32x32/svg/house.svg +1 -0
  148. package/src/lib/Icon/icons/32x32/svg/image.svg +1 -0
  149. package/src/lib/Icon/icons/32x32/svg/info.svg +1 -0
  150. package/src/lib/Icon/icons/32x32/svg/invite_neighbour.svg +1 -0
  151. package/src/lib/Icon/icons/32x32/svg/key.svg +1 -0
  152. package/src/lib/Icon/icons/32x32/svg/kitchen_pot.svg +1 -0
  153. package/src/lib/Icon/icons/32x32/svg/list.svg +1 -0
  154. package/src/lib/Icon/icons/32x32/svg/log_out.svg +1 -0
  155. package/src/lib/Icon/icons/32x32/svg/loudspeaker.svg +1 -0
  156. package/src/lib/Icon/icons/32x32/svg/map.svg +1 -0
  157. package/src/lib/Icon/icons/32x32/svg/marketplace.svg +1 -0
  158. package/src/lib/Icon/icons/32x32/svg/miscellaneous_other.svg +1 -0
  159. package/src/lib/Icon/icons/32x32/svg/more_dots.svg +1 -0
  160. package/src/lib/Icon/icons/32x32/svg/more_dots_alt.svg +1 -0
  161. package/src/lib/Icon/icons/32x32/svg/music.svg +1 -0
  162. package/src/lib/Icon/icons/32x32/svg/nebenan.de.svg +1 -0
  163. package/src/lib/Icon/icons/32x32/svg/neighbour.svg +1 -0
  164. package/src/lib/Icon/icons/32x32/svg/notification_bell.svg +1 -0
  165. package/src/lib/Icon/icons/32x32/svg/organisation.svg +1 -0
  166. package/src/lib/Icon/icons/32x32/svg/paper_form_empty.svg +1 -0
  167. package/src/lib/Icon/icons/32x32/svg/paper_form_filled.svg +1 -0
  168. package/src/lib/Icon/icons/32x32/svg/paperclip.svg +1 -0
  169. package/src/lib/Icon/icons/32x32/svg/paw.svg +1 -0
  170. package/src/lib/Icon/icons/32x32/svg/pencil.svg +1 -0
  171. package/src/lib/Icon/icons/32x32/svg/pin.svg +1 -0
  172. package/src/lib/Icon/icons/32x32/svg/pins.svg +1 -0
  173. package/src/lib/Icon/icons/32x32/svg/plant.svg +1 -0
  174. package/src/lib/Icon/icons/32x32/svg/plus.svg +1 -0
  175. package/src/lib/Icon/icons/32x32/svg/plus_circle.svg +1 -0
  176. package/src/lib/Icon/icons/32x32/svg/post.svg +1 -0
  177. package/src/lib/Icon/icons/32x32/svg/privacy_lock.svg +1 -0
  178. package/src/lib/Icon/icons/32x32/svg/qr_code.svg +1 -0
  179. package/src/lib/Icon/icons/32x32/svg/search.svg +1 -0
  180. package/src/lib/Icon/icons/32x32/svg/settings_cog.svg +1 -0
  181. package/src/lib/Icon/icons/32x32/svg/shopping_bag.svg +1 -0
  182. package/src/lib/Icon/icons/32x32/svg/shopping_cart.svg +1 -0
  183. package/src/lib/Icon/icons/32x32/svg/special_place.svg +1 -0
  184. package/src/lib/Icon/icons/32x32/svg/suitcase.svg +1 -0
  185. package/src/lib/Icon/icons/32x32/svg/supporter.svg +1 -0
  186. package/src/lib/Icon/icons/32x32/svg/tennis_ball.svg +1 -0
  187. package/src/lib/Icon/icons/32x32/svg/thanks.svg +1 -0
  188. package/src/lib/Icon/icons/32x32/svg/trash_can.svg +1 -0
  189. package/src/lib/Icon/icons/32x32/svg/truck.svg +1 -0
  190. package/src/lib/Icon/icons/32x32/svg/user.svg +1 -0
  191. package/src/lib/Icon/icons/32x32/svg/user_profile.svg +1 -0
  192. package/src/lib/Icon/icons/32x32/svg/wellness.svg +1 -0
  193. package/src/lib/Icon/icons/index.ts +9 -0
  194. package/src/lib/IconButton/IconButton.module.scss +36 -0
  195. package/src/lib/IconButton/IconButton.spec.tsx +56 -0
  196. package/src/lib/IconButton/IconButton.stories.tsx +36 -0
  197. package/src/lib/IconButton/IconButton.tsx +25 -0
  198. package/{lib/IconButton/IconButton.types.d.ts → src/lib/IconButton/IconButton.types.ts} +10 -10
  199. package/src/lib/IconButton/utils.ts +6 -0
  200. package/src/lib/Image/Image.spec.tsx +10 -0
  201. package/src/lib/Image/Image.tsx +7 -0
  202. package/src/lib/Image/Image.type.tsx +5 -0
  203. package/src/lib/LabelPill/LabelPill.module.scss +33 -0
  204. package/src/lib/LabelPill/LabelPill.spec.tsx +23 -0
  205. package/src/lib/LabelPill/LabelPill.stories.tsx +31 -0
  206. package/src/lib/LabelPill/LabelPill.tsx +16 -0
  207. package/src/lib/LabelPill/LabelPill.types.ts +4 -0
  208. package/src/lib/Legend/Legend.module.scss +9 -0
  209. package/src/lib/Legend/Legend.spec.tsx +39 -0
  210. package/src/lib/Legend/Legend.stories.ts +39 -0
  211. package/src/lib/Legend/Legend.tsx +19 -0
  212. package/src/lib/Legend/Legend.types.ts +5 -0
  213. package/src/lib/MenuItem/MenuItem.module.scss +70 -0
  214. package/src/lib/MenuItem/MenuItem.spec.tsx +47 -0
  215. package/src/lib/MenuItem/MenuItem.stories.tsx +97 -0
  216. package/src/lib/MenuItem/MenuItem.tsx +34 -0
  217. package/src/lib/MenuItem/MenuItem.types.ts +10 -0
  218. package/src/lib/NotificationBubble/NotificationBubble.module.scss +30 -0
  219. package/src/lib/NotificationBubble/NotificationBubble.spec.tsx +36 -0
  220. package/src/lib/NotificationBubble/NotificationBubble.stories.tsx +56 -0
  221. package/src/lib/NotificationBubble/NotificationBubble.tsx +34 -0
  222. package/{lib/NotificationBubble/NotificationBubble.types.d.ts → src/lib/NotificationBubble/NotificationBubble.types.tsx} +3 -2
  223. package/src/lib/Thumbnail/Thumbnail.module.scss +67 -0
  224. package/src/lib/Thumbnail/Thumbnail.spec.tsx +51 -0
  225. package/src/lib/Thumbnail/Thumbnail.stories.tsx +242 -0
  226. package/src/lib/Thumbnail/Thumbnail.tsx +28 -0
  227. package/src/lib/Thumbnail/Thumbnail.type.tsx +18 -0
  228. package/src/lib/Toggle/Toggle.module.scss +53 -0
  229. package/src/lib/Toggle/Toggle.spec.tsx +23 -0
  230. package/src/lib/Toggle/Toggle.stories.tsx +38 -0
  231. package/src/lib/Toggle/Toggle.tsx +32 -0
  232. package/{lib/Toggle/Toggle.types.d.ts → src/lib/Toggle/Toggle.types.ts} +3 -2
  233. package/src/lib/ToggleInput/ToggleInput.module.scss +33 -0
  234. package/src/lib/ToggleInput/ToggleInput.spec.tsx +45 -0
  235. package/src/lib/ToggleInput/ToggleInput.stories.tsx +62 -0
  236. package/src/lib/ToggleInput/ToggleInput.tsx +40 -0
  237. package/{lib/ToggleInput/ToggleInput.types.d.ts → src/lib/ToggleInput/ToggleInput.types.ts} +5 -3
  238. package/src/lib/Typography/Typography.module.scss +61 -0
  239. package/src/lib/Typography/Typography.spec.tsx +60 -0
  240. package/src/lib/Typography/Typography.stories.tsx +45 -0
  241. package/src/lib/Typography/Typography.tsx +26 -0
  242. package/src/lib/Typography/Typography.types.ts +28 -0
  243. package/src/styles/_design-tokens.scss +1 -0
  244. package/src/styles/_fonts.scss +0 -0
  245. package/src/styles/_functions.scss +17 -0
  246. package/src/styles/_mixins.scss +33 -0
  247. package/src/styles/index.scss +3 -0
  248. package/src/styles/reset.scss +65 -0
  249. package/tsconfig.json +24 -0
  250. package/tsconfig.lib.json +35 -0
  251. package/tsconfig.spec.json +20 -0
  252. package/tsconfig.storybook.json +31 -0
  253. package/vite.config.ts +57 -0
  254. package/index.js +0 -93
  255. package/index.mjs +0 -4258
  256. package/lib/BaseButton/BaseButton.d.ts +0 -11
  257. package/lib/Card/Card.d.ts +0 -3
  258. package/lib/Card/Card.types.d.ts +0 -10
  259. package/lib/Card/Card.utils.d.ts +0 -3
  260. package/lib/Card/CardBody/CardBody.d.ts +0 -3
  261. package/lib/Card/CardBody/CardBody.types.d.ts +0 -5
  262. package/lib/Card/CardHeader/CardHeader.d.ts +0 -3
  263. package/lib/Card/CardHeader/CardHeader.type.d.ts +0 -10
  264. package/lib/ContentCreatorButton/ContentCreatorButton.d.ts +0 -3
  265. package/lib/Divider/Divider.d.ts +0 -3
  266. package/lib/Divider/Divider.types.d.ts +0 -6
  267. package/lib/Fieldset/Fieldset.d.ts +0 -3
  268. package/lib/Fieldset/Fieldset.types.d.ts +0 -8
  269. package/lib/Form/Form.d.ts +0 -3
  270. package/lib/Form/Form.types.d.ts +0 -10
  271. package/lib/Icon/Icon.d.ts +0 -4
  272. package/lib/Icon/Icon.types.d.ts +0 -18
  273. package/lib/Icon/icons/24x24/index.d.ts +0 -130
  274. package/lib/Icon/icons/32x32/index.d.ts +0 -265
  275. package/lib/Icon/icons/index.d.ts +0 -395
  276. package/lib/IconButton/IconButton.d.ts +0 -3
  277. package/lib/IconButton/utils.d.ts +0 -3
  278. package/lib/Image/Image.d.ts +0 -3
  279. package/lib/Image/Image.type.d.ts +0 -5
  280. package/lib/LabelPill/LabelPill.d.ts +0 -3
  281. package/lib/LabelPill/LabelPill.types.d.ts +0 -4
  282. package/lib/Legend/Legend.d.ts +0 -3
  283. package/lib/Legend/Legend.types.d.ts +0 -5
  284. package/lib/MenuItem/MenuItem.d.ts +0 -3
  285. package/lib/MenuItem/MenuItem.types.d.ts +0 -9
  286. package/lib/NotificationBubble/NotificationBubble.d.ts +0 -3
  287. package/lib/Toggle/Toggle.d.ts +0 -3
  288. package/lib/ToggleInput/ToggleInput.d.ts +0 -3
  289. package/lib/Typography/Typography.d.ts +0 -3
  290. package/lib/Typography/Typography.types.d.ts +0 -8
  291. package/style.css +0 -1
@@ -0,0 +1,97 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { BrowserRouter } from 'react-router-dom';
3
+
4
+ import Icon from '../Icon/Icon';
5
+ import NotificationBubble from '../NotificationBubble/NotificationBubble';
6
+
7
+ import MenuItem from './MenuItem';
8
+
9
+ const meta: Meta<typeof MenuItem> = {
10
+ argTypes: {
11
+ labelPillText: {
12
+ control: {
13
+ type: 'text',
14
+ },
15
+ description: 'This will be text of the label pill',
16
+ },
17
+ leftIcon: {
18
+ control: false,
19
+ description: 'This will be left icon of the menu item',
20
+ },
21
+ onBlur: {
22
+ action: 'blurred',
23
+ description: 'On blur event callback',
24
+ },
25
+ onClick: { action: 'clicked', description: 'On click event callback' },
26
+ referrerPolicy: {
27
+ control: {
28
+ type: 'select',
29
+ },
30
+ defaultValue: 'no-referrer',
31
+ description: 'Referrer policy for the link',
32
+ options: ['no-referrer', 'origin', 'unsafe-url'],
33
+ },
34
+ rightIcon: {
35
+ control: false,
36
+ description: 'This will be right icon of the menu item',
37
+ },
38
+
39
+ target: {
40
+ control: {
41
+ type: 'select',
42
+ },
43
+ defaultValue: '_self',
44
+ description:
45
+ "Target attribute for the link '_blank' | '_self' | '_parent' | '_top'",
46
+ options: ['_blank', '_self', '_parent', '_top'],
47
+ },
48
+
49
+ text: {
50
+ control: {
51
+ type: 'text',
52
+ },
53
+ defaultValue: 'Home',
54
+ description: 'This will be text of the menu item',
55
+ },
56
+
57
+ to: {
58
+ control: {
59
+ type: 'text',
60
+ },
61
+ description: 'This will be the link of the menu item',
62
+ },
63
+ },
64
+ component: MenuItem,
65
+ decorators: [
66
+ (Story) => (
67
+ <BrowserRouter>
68
+ <Story />
69
+ </BrowserRouter>
70
+ ),
71
+ ],
72
+ title: 'Components/MenuItem',
73
+ };
74
+
75
+ export default meta;
76
+
77
+ type Story = StoryObj<typeof MenuItem>;
78
+
79
+ export const Primary: Story = {
80
+ args: {
81
+ labelPillText: 'New',
82
+ leftIcon: (
83
+ <NotificationBubble ariaLabel="Notifications">
84
+ <Icon name="nebenan_de" size="32" />
85
+ </NotificationBubble>
86
+ ),
87
+ rightIcon: <Icon name="chevron_down" size="24" />,
88
+ text: 'Home',
89
+ to: '/',
90
+ },
91
+ parameters: {
92
+ design: {
93
+ type: 'figma',
94
+ url: 'https://www.figma.com/file/hN7xJ3rRAemUJT9T0uEfUS/Product-Design-System?type=design&node-id=3709-7139&mode=design&t=ugANsqRffu1KkyuR-0',
95
+ },
96
+ },
97
+ };
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+ import clsx from 'clsx';
3
+
4
+ import { BaseButton, LabelPill, Typography } from '@goodhood-web/ui';
5
+
6
+ import styles from './MenuItem.module.scss';
7
+ import { MenuItemProps } from './MenuItem.types';
8
+
9
+ const MenuItem = ({
10
+ isSelected,
11
+ labelPillText,
12
+ leftIcon,
13
+ onClick,
14
+ rightIcon,
15
+ text,
16
+ }: MenuItemProps) => (
17
+ <BaseButton
18
+ onClick={onClick}
19
+ className={clsx(styles.menuItem, {
20
+ [styles['menuItem--selected']]: isSelected,
21
+ })}
22
+ >
23
+ <span className={clsx(styles.highlightFrame)}>
24
+ {leftIcon}
25
+ <Typography type="body-large" as="span">
26
+ {text}
27
+ </Typography>
28
+ <LabelPill label={labelPillText} size="small" />
29
+ <span className={styles.rightIcon}>{rightIcon}</span>
30
+ </span>
31
+ </BaseButton>
32
+ );
33
+
34
+ export default MenuItem;
@@ -0,0 +1,10 @@
1
+ import { ReactNode } from 'react';
2
+
3
+ export interface MenuItemProps {
4
+ isSelected?: boolean;
5
+ labelPillText: string;
6
+ leftIcon: ReactNode;
7
+ onClick: () => void;
8
+ rightIcon: ReactNode;
9
+ text: string;
10
+ }
@@ -0,0 +1,30 @@
1
+ .bubbleContent {
2
+ position: relative;
3
+ display: inline-block;
4
+ }
5
+
6
+ .bubble {
7
+ position: absolute;
8
+ z-index: auto;
9
+ top: 6px;
10
+ right: 6px;
11
+ display: flex;
12
+ width: 20px;
13
+ height: 20px;
14
+ align-items: center;
15
+ justify-content: center;
16
+ border-radius: 50%;
17
+ background-color: getSemanticColor(highlight, highlight);
18
+ color: getSemanticColor(highlight, onHighlight);
19
+ font-size: 12px;
20
+ font-weight: bold;
21
+ text-align: center;
22
+ transform: translate(50%, -50%);
23
+ transform-origin: 100% 0;
24
+ white-space: nowrap;
25
+
26
+ &--empty {
27
+ width: 12px;
28
+ height: 12px;
29
+ }
30
+ }
@@ -0,0 +1,36 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render, screen } from '@testing-library/react';
3
+ import React from 'react';
4
+
5
+ import NotificationBubble from './NotificationBubble';
6
+ import { NotificationBubbleProps } from './NotificationBubble.types';
7
+
8
+ describe('NotificationBubble', () => {
9
+ it('renders the bubble with a value', () => {
10
+ const props: NotificationBubbleProps = {
11
+ ariaLabel: 'Notification Bubble',
12
+ value: 5,
13
+ };
14
+
15
+ render(<NotificationBubble {...props}>Content</NotificationBubble>);
16
+
17
+ const bubble = screen.getByRole('status', { name: 'Notification Bubble' });
18
+ const badge = screen.getByText('5');
19
+ expect(bubble).toBeInTheDocument();
20
+ expect(badge).toBeInTheDocument();
21
+ });
22
+
23
+ it('renders the bubble without a value', () => {
24
+ const props: NotificationBubbleProps = {
25
+ ariaLabel: 'Notification Bubble',
26
+ value: undefined,
27
+ };
28
+
29
+ render(<NotificationBubble {...props}>Content</NotificationBubble>);
30
+
31
+ const bubble = screen.getByRole('status', { name: 'Notification Bubble' });
32
+ const badge = screen.queryByText('0'); // Modify this to match the expected behavior
33
+ expect(bubble).toBeInTheDocument();
34
+ expect(badge).toBeNull(); // Check that badge is not present
35
+ });
36
+ });
@@ -0,0 +1,56 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import BaseButton from '../BaseButton/BaseButton';
4
+ import Icon from '../Icon/Icon';
5
+
6
+ import NotificationBubble from './NotificationBubble';
7
+
8
+ const meta: Meta<typeof NotificationBubble> = {
9
+ argTypes: {
10
+ children: {
11
+ control: { type: 'select' },
12
+ mapping: {
13
+ Button: (
14
+ <BaseButton
15
+ onClick={() => {
16
+ // do nothing
17
+ }}
18
+ >
19
+ Button
20
+ </BaseButton>
21
+ ),
22
+ Icon: <Icon name="envelope" size="32" />,
23
+ },
24
+ // TODO replace with actual use case from our new design system (Icon etc)
25
+ options: ['Icon', 'Button'],
26
+ },
27
+ },
28
+ args: {
29
+ children: 'Icon',
30
+ },
31
+ component: NotificationBubble,
32
+ parameters: {
33
+ design: {
34
+ type: 'figma',
35
+ url: 'https://www.figma.com/file/hN7xJ3rRAemUJT9T0uEfUS/Product-Design-System?type=design&node-id=237-3029&mode=design',
36
+ },
37
+ },
38
+ title: 'Components/NotificationBubble',
39
+ };
40
+
41
+ export default meta;
42
+
43
+ type Story = StoryObj<typeof NotificationBubble>;
44
+
45
+ export const Primary: Story = {
46
+ args: {
47
+ ariaLabel: '5 new messages',
48
+ value: 5,
49
+ },
50
+ };
51
+
52
+ export const Empty: Story = {
53
+ args: {
54
+ ariaLabel: 'Messages',
55
+ },
56
+ };
@@ -0,0 +1,34 @@
1
+ import { Badge } from '@mui/base';
2
+ import clsx from 'clsx';
3
+
4
+ import styles from './NotificationBubble.module.scss';
5
+ import { NotificationBubbleProps } from './NotificationBubble.types';
6
+
7
+ const MAX_COUNT = 9;
8
+
9
+ const NotificationBubble = (props: NotificationBubbleProps) => {
10
+ const { ariaLabel, children, value } = props;
11
+
12
+ const displayValue = value && value < 0 ? 0 : value;
13
+ const classes = clsx(
14
+ {
15
+ [styles['bubble--empty']]: displayValue === undefined,
16
+ },
17
+ styles.bubble,
18
+ );
19
+
20
+ return (
21
+ <Badge
22
+ badgeContent={displayValue}
23
+ className={styles.bubbleContent}
24
+ max={MAX_COUNT}
25
+ slotProps={{ badge: { className: classes } }}
26
+ aria-label={ariaLabel}
27
+ role="status"
28
+ >
29
+ {children}
30
+ </Badge>
31
+ );
32
+ };
33
+
34
+ export default NotificationBubble;
@@ -1,5 +1,6 @@
1
1
  import { BadgeOwnProps } from '@mui/base';
2
+
2
3
  export interface NotificationBubbleProps extends BadgeOwnProps {
3
- ariaLabel?: string;
4
- value?: number;
4
+ ariaLabel?: string;
5
+ value?: number;
5
6
  }
@@ -0,0 +1,67 @@
1
+ /*
2
+ * Replace this with your own classes
3
+ *
4
+ * e.g.
5
+ * .container {
6
+ * }
7
+ */
8
+
9
+ @mixin setSizes {
10
+ $sizes: (24, 28, 32, 40, 48, 56, 64, 80, 120, 280);
11
+
12
+ @each $size in $sizes {
13
+ &--#{$size} {
14
+ width: #{$size}px;
15
+ height: #{$size}px;
16
+ }
17
+ }
18
+ }
19
+
20
+ .root {
21
+ @include setSizes;
22
+ position: relative;
23
+ overflow: hidden;
24
+ border: solid 1px getSemanticColor('outline', 'outlineVariant');
25
+ background-color: getSemanticColor('outline', 'outlineVariant');
26
+
27
+ &--square {
28
+ &.root--24,
29
+ &.root--32 {
30
+ border-radius: getBorderRadius('xs');
31
+ }
32
+ &.root--40,
33
+ &.root--48 {
34
+ border-radius: getBorderRadius('sm');
35
+ }
36
+ &.root--56,
37
+ &.root--64 {
38
+ border-radius: getBorderRadius('md');
39
+ }
40
+ &.root--80,
41
+ &.root--120 {
42
+ border-radius: getBorderRadius('lg');
43
+ }
44
+ }
45
+
46
+ &--circular {
47
+ border-radius: 50%;
48
+ }
49
+
50
+ &--isPlaceholder {
51
+ &::before {
52
+ position: absolute;
53
+ z-index: 1;
54
+ width: 100%;
55
+ height: 100%;
56
+ background-color: getSemanticColor('outline', 'outlineVariant');
57
+ content: '';
58
+ opacity: 0.4;
59
+ }
60
+ }
61
+
62
+ img {
63
+ width: 100%;
64
+ height: 100%;
65
+ object-fit: cover;
66
+ }
67
+ }
@@ -0,0 +1,51 @@
1
+ import '@testing-library/jest-dom';
2
+ import { render } from '@testing-library/react';
3
+
4
+ import Thumbnail from './Thumbnail';
5
+ import { ThumbnailCircularProps, ThumbnailSquareProps } from './Thumbnail.type';
6
+
7
+ describe('Thumbnail component', () => {
8
+ it('renders a valid circular thumbnail', () => {
9
+ const circularProps = {
10
+ alt: 'Test Image',
11
+ shape: 'circular',
12
+ size: '40',
13
+ src: 'test.jpg',
14
+ };
15
+ const { container } = render(
16
+ <Thumbnail {...(circularProps as ThumbnailCircularProps)} />,
17
+ );
18
+
19
+ const thumbnail = container.querySelector('.root--circular');
20
+ expect(thumbnail).toBeInTheDocument();
21
+ });
22
+
23
+ it('renders a valid square thumbnail', () => {
24
+ const squareProps = {
25
+ alt: 'Test Image',
26
+ shape: 'square',
27
+ size: '40',
28
+ src: 'test.jpg',
29
+ };
30
+ const { container } = render(
31
+ <Thumbnail {...(squareProps as ThumbnailSquareProps)} />,
32
+ );
33
+ const thumbnail = container.querySelector('.root--square');
34
+ expect(thumbnail).toBeInTheDocument();
35
+ });
36
+
37
+ it('does not display image when src is not provided', () => {
38
+ const circularEmptySrcProps = {
39
+ alt: 'Test Image',
40
+ shape: 'circular',
41
+ size: '24',
42
+ src: '',
43
+ };
44
+ const { queryByAltText } = render(
45
+ <Thumbnail {...(circularEmptySrcProps as ThumbnailSquareProps)} />,
46
+ );
47
+ expect(queryByAltText('Test Image')).not.toBeInTheDocument();
48
+ });
49
+
50
+ // Add more test cases for different scenarios
51
+ });
@@ -0,0 +1,242 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import Thumbnail from './Thumbnail';
4
+ import { TCircularSize, TSquareSize } from './Thumbnail.type';
5
+
6
+ const circularSizes = ['28', '32', '40', '48', '56', '80', '120', '280'];
7
+ const squareSizes = ['24', '32', '40', '48', '56', '64', '80', '120'];
8
+ const imgSrc = 'https://placekitten.com/640/360';
9
+ const meta: Meta<typeof Thumbnail> = {
10
+ component: Thumbnail,
11
+ title: 'Components/Thumbnail',
12
+ };
13
+ export default meta;
14
+
15
+ type Story = StoryObj<typeof Thumbnail>;
16
+
17
+ export const Primary: Story = {
18
+ argTypes: {
19
+ alt: {
20
+ description:
21
+ 'The "alt" attribute provides descriptive text for an image, ensuring accessibility by offering an alternative description.',
22
+ },
23
+ isPlaceholder: {
24
+ active: { control: 'boolean' },
25
+ defaultValue: { summary: false },
26
+ description:
27
+ 'The isPlaceholder property is used to add a background color overlay to the component, indicating they are temporary.',
28
+ },
29
+ shape: {
30
+ control: { type: 'radio' },
31
+ description:
32
+ 'The "shape" property defines the component\'s visual form, with options "circular" or "square."',
33
+ options: ['circular', 'square'],
34
+ },
35
+ size: {
36
+ control: {
37
+ readonly: true,
38
+ type: 'string',
39
+ },
40
+ description:
41
+ 'To view the available sizes, please refer to the individual stories that showcase the shape variations.',
42
+ },
43
+ src: {
44
+ description:
45
+ 'The "src" attribute specifies the image source, indicating the location from which the image is loaded.',
46
+ },
47
+ },
48
+ args: {
49
+ alt: 'component image',
50
+ isPlaceholder: false,
51
+ shape: 'circular',
52
+ size: '80',
53
+ src: imgSrc,
54
+ },
55
+ parameters: {
56
+ design: {
57
+ type: 'figma',
58
+ url: 'https://www.figma.com/file/hN7xJ3rRAemUJT9T0uEfUS/Product-Design-System?type=design&node-id=116-2637&mode=design&t=0zWTONm1DR992lT9-0',
59
+ },
60
+ },
61
+ };
62
+
63
+ export const Circular: Story = {
64
+ argTypes: {
65
+ alt: {
66
+ control: { readonly: true, type: 'string' },
67
+ },
68
+ isPlaceholder: {
69
+ control: { readonly: true, type: 'string' },
70
+ },
71
+ shape: {
72
+ control: { readonly: true, type: 'string' },
73
+ description: 'circular',
74
+ },
75
+ size: {
76
+ control: {
77
+ type: 'select',
78
+ },
79
+ description: `The size property allows you to choose from predefined options like
80
+ "28", "32", "40", "48", "56", "80", "120" or "280" to specify the element's dimensions or scale in pixels (px).`,
81
+ options: circularSizes,
82
+ },
83
+ src: {
84
+ control: { readonly: true, type: 'string' },
85
+ },
86
+ },
87
+ args: {
88
+ shape: 'circular',
89
+ size: '48',
90
+ src: imgSrc,
91
+ },
92
+ parameters: {
93
+ a11y: {
94
+ disable: true,
95
+ },
96
+ actions: {
97
+ disable: true,
98
+ },
99
+ design: {
100
+ type: 'figma',
101
+ url: 'https://www.figma.com/file/hN7xJ3rRAemUJT9T0uEfUS/Product-Design-System?node-id=116%3A2649&mode=dev',
102
+ },
103
+ },
104
+ render: (args) => (
105
+ <div
106
+ style={{
107
+ display: 'flex',
108
+ flexWrap: 'wrap',
109
+ gap: '32px',
110
+ justifyContent: 'space-between',
111
+ }}
112
+ >
113
+ <div style={{ display: 'flex', height: '280px', width: '280px' }}>
114
+ <Thumbnail
115
+ shape="circular"
116
+ src={imgSrc}
117
+ size={args?.size as TCircularSize}
118
+ alt=""
119
+ />
120
+ </div>
121
+ <div
122
+ style={{
123
+ alignItems: 'start',
124
+ display: 'flex',
125
+ flexWrap: 'wrap',
126
+ gap: '16px',
127
+ justifyContent: 'center',
128
+ }}
129
+ >
130
+ {circularSizes.map((size) => {
131
+ return (
132
+ <div
133
+ key={size}
134
+ style={{
135
+ alignItems: 'center',
136
+ display: 'flex',
137
+ flexDirection: 'column',
138
+ justifyContent: 'center',
139
+ }}
140
+ >
141
+ <h2>{size}</h2>
142
+ <Thumbnail
143
+ shape="circular"
144
+ src={imgSrc}
145
+ size={`${size}` as TCircularSize}
146
+ alt={size}
147
+ />
148
+ </div>
149
+ );
150
+ })}
151
+ </div>
152
+ </div>
153
+ ),
154
+ };
155
+
156
+ export const Square: Story = {
157
+ argTypes: {
158
+ alt: {
159
+ control: { readonly: true, type: 'string' },
160
+ },
161
+ isPlaceholder: {
162
+ control: { readonly: true, type: 'string' },
163
+ },
164
+ shape: {
165
+ control: { readonly: true, type: 'string' },
166
+ description: 'square',
167
+ },
168
+ size: {
169
+ control: {
170
+ type: 'select',
171
+ },
172
+ description: `The size property allows you to choose from predefined options like
173
+ "24", "32", "40", "48", "56", "64", "80" or "120" to specify the element's dimensions or scale in pixels (px).`,
174
+ options: squareSizes,
175
+ },
176
+ src: {
177
+ control: { readonly: true, type: 'string' },
178
+ },
179
+ },
180
+ args: {
181
+ shape: 'square',
182
+ size: '48',
183
+ src: imgSrc,
184
+ },
185
+ parameters: {
186
+ a11y: {
187
+ disable: true,
188
+ },
189
+ actions: {
190
+ disable: true,
191
+ },
192
+ design: {
193
+ type: 'figma',
194
+ url: 'https://www.figma.com/file/hN7xJ3rRAemUJT9T0uEfUS/Product-Design-System?type=design&node-id=119-2453&mode=design&t=tRDkebYkaf8rn7Vz-0',
195
+ },
196
+ },
197
+ render: (args) => (
198
+ <div
199
+ style={{
200
+ display: 'flex',
201
+ flexWrap: 'wrap',
202
+ gap: '32px',
203
+ justifyContent: 'space-between',
204
+ }}
205
+ >
206
+ <div style={{ display: 'flex', height: '120px', width: '120px' }}>
207
+ <Thumbnail shape="square" src={imgSrc} size={args?.size as TSquareSize} alt="" />
208
+ </div>
209
+ <div
210
+ style={{
211
+ alignItems: 'start',
212
+ display: 'flex',
213
+ flexWrap: 'wrap',
214
+ gap: '16px',
215
+ justifyContent: 'center',
216
+ }}
217
+ >
218
+ {squareSizes.map((size) => {
219
+ return (
220
+ <div
221
+ key={size}
222
+ style={{
223
+ alignItems: 'center',
224
+ display: 'flex',
225
+ flexDirection: 'column',
226
+ justifyContent: 'center',
227
+ }}
228
+ >
229
+ <h2>{size}</h2>
230
+ <Thumbnail
231
+ shape="square"
232
+ src={imgSrc}
233
+ size={`${size}` as TSquareSize}
234
+ alt={size}
235
+ />
236
+ </div>
237
+ );
238
+ })}
239
+ </div>
240
+ </div>
241
+ ),
242
+ };
@@ -0,0 +1,28 @@
1
+ import clsx from 'clsx';
2
+
3
+ import Image from '../Image/Image';
4
+
5
+ import styles from './Thumbnail.module.scss';
6
+ import { ThumbnailCircularProps, ThumbnailSquareProps } from './Thumbnail.type';
7
+
8
+ const Thumbnail = ({
9
+ alt,
10
+ isPlaceholder,
11
+ shape,
12
+ size,
13
+ src,
14
+ }: ThumbnailCircularProps | ThumbnailSquareProps) => {
15
+ const thumbnailIsPlaceholder = styles['root--isPlaceholder'];
16
+
17
+ return (
18
+ <div
19
+ className={clsx(styles.root, styles[`root--${size}`], styles[`root--${shape}`], {
20
+ [thumbnailIsPlaceholder]: isPlaceholder,
21
+ })}
22
+ >
23
+ {src && <Image src={src} alt={alt} />}
24
+ </div>
25
+ );
26
+ };
27
+
28
+ export default Thumbnail;