@adobe-commerce/elsie 1.0.0-alpha04071347

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 (340) hide show
  1. package/.elsie.js +21 -0
  2. package/.eslintrc.js +18 -0
  3. package/README.md +52 -0
  4. package/__mocks__/svg.js +11 -0
  5. package/bin/builders/build/index.js +20 -0
  6. package/bin/builders/generate/api/index.js +65 -0
  7. package/bin/builders/generate/api/templates/function.js +9 -0
  8. package/bin/builders/generate/api/templates/index.js +7 -0
  9. package/bin/builders/generate/api/templates/story.js +23 -0
  10. package/bin/builders/generate/api/templates/unit-test.js +15 -0
  11. package/bin/builders/generate/component/index.js +87 -0
  12. package/bin/builders/generate/component/templates/Component.js +43 -0
  13. package/bin/builders/generate/component/templates/css.js +24 -0
  14. package/bin/builders/generate/component/templates/index.js +8 -0
  15. package/bin/builders/generate/component/templates/stories.js +46 -0
  16. package/bin/builders/generate/component/templates/unit-test.js +19 -0
  17. package/bin/builders/generate/config/index.js +54 -0
  18. package/bin/builders/generate/config/templates/elsie.js +29 -0
  19. package/bin/builders/generate/container/index.js +65 -0
  20. package/bin/builders/generate/container/templates/Component.js +18 -0
  21. package/bin/builders/generate/container/templates/index.js +8 -0
  22. package/bin/builders/generate/container/templates/stories.js +34 -0
  23. package/bin/builders/generate/container/templates/unit-test.js +19 -0
  24. package/bin/builders/generate/index.js +283 -0
  25. package/bin/builders/gql/createOrClearDirectory.js +33 -0
  26. package/bin/builders/gql/getSchemaRef.js +25 -0
  27. package/bin/builders/gql/index.js +71 -0
  28. package/bin/builders/lint/index.js +5 -0
  29. package/bin/builders/serve/index.js +44 -0
  30. package/bin/builders/storybook/index.js +5 -0
  31. package/bin/builders/test/index.js +5 -0
  32. package/bin/index.js +26 -0
  33. package/bin/lib/cli.js +8 -0
  34. package/bin/lib/config.js +12 -0
  35. package/bin/lib/log-message.js +11 -0
  36. package/bin/lib/string.js +26 -0
  37. package/bin/lib/validate-typeof.js +28 -0
  38. package/bin/lib/write-file.js +30 -0
  39. package/bin/lib/write-parent-index.js +45 -0
  40. package/config/eslint.js +113 -0
  41. package/config/jest.js +90 -0
  42. package/config/prettier.js +16 -0
  43. package/config/setEnvVars.js +14 -0
  44. package/config/storybook/addon.js +130 -0
  45. package/config/storybook/components/FileTree/FileTree.jsx +192 -0
  46. package/config/storybook/components/FileTree/index.js +10 -0
  47. package/config/storybook/components/Flex/Flex.jsx +21 -0
  48. package/config/storybook/components/Flex/Flex.module.css +29 -0
  49. package/config/storybook/components/Flex/index.js +10 -0
  50. package/config/storybook/components/OptionsTable/OptionsTable.jsx +88 -0
  51. package/config/storybook/components/OptionsTable/OptionsTable.module.css +104 -0
  52. package/config/storybook/components/OptionsTable/index.js +10 -0
  53. package/config/storybook/components/Panel/Panel.module.css +56 -0
  54. package/config/storybook/components/Panel/Panel.tsx +46 -0
  55. package/config/storybook/components/Panel/index.ts +10 -0
  56. package/config/storybook/components/Screenshot/Screenshot.jsx +23 -0
  57. package/config/storybook/components/Screenshot/Screenshot.module.css +28 -0
  58. package/config/storybook/components/Screenshot/index.js +10 -0
  59. package/config/storybook/components/Steps/Steps.jsx +21 -0
  60. package/config/storybook/components/Steps/Steps.module.css +43 -0
  61. package/config/storybook/components/Steps/index.js +10 -0
  62. package/config/storybook/components/StoryWrapper/StoryWrapper.jsx +18 -0
  63. package/config/storybook/components/StoryWrapper/StoryWrapper.module.css +22 -0
  64. package/config/storybook/components/StoryWrapper/index.js +10 -0
  65. package/config/storybook/components/Summary/Summary.jsx +19 -0
  66. package/config/storybook/components/Summary/Summary.module.css +20 -0
  67. package/config/storybook/components/Summary/index.js +10 -0
  68. package/config/storybook/components/Variants/Variants.js +57 -0
  69. package/config/storybook/components/Variants/docs.css +48 -0
  70. package/config/storybook/components/Variants/index.js +10 -0
  71. package/config/storybook/components/video/index.jsx +28 -0
  72. package/config/storybook/manager.js +23 -0
  73. package/config/storybook/preview.jsx +88 -0
  74. package/config/storybook/theming/fonts.css +68 -0
  75. package/config/storybook/theming/logo.svg +19 -0
  76. package/config/storybook/theming/manager.css +63 -0
  77. package/config/storybook/theming/preview.css +93 -0
  78. package/config/storybook/theming/theme.js +61 -0
  79. package/config/tsconfig-base.json +16 -0
  80. package/config/tsconfig-preact.json +15 -0
  81. package/config/vite.mjs +306 -0
  82. package/package.json +113 -0
  83. package/post-release.sh +5 -0
  84. package/src/components/Accordion/Accordion.css +88 -0
  85. package/src/components/Accordion/Accordion.stories.tsx +582 -0
  86. package/src/components/Accordion/Accordion.tsx +177 -0
  87. package/src/components/Accordion/index.ts +11 -0
  88. package/src/components/ActionButton/ActionButton.css +100 -0
  89. package/src/components/ActionButton/ActionButton.stories.tsx +169 -0
  90. package/src/components/ActionButton/ActionButton.tsx +53 -0
  91. package/src/components/ActionButton/index.ts +10 -0
  92. package/src/components/ActionButtonGroup/ActionButtonGroup.css +77 -0
  93. package/src/components/ActionButtonGroup/ActionButtonGroup.stories.tsx +97 -0
  94. package/src/components/ActionButtonGroup/ActionButtonGroup.tsx +91 -0
  95. package/src/components/ActionButtonGroup/index.ts +10 -0
  96. package/src/components/AlertBanner/AlertBanner.css +144 -0
  97. package/src/components/AlertBanner/AlertBanner.stories.tsx +165 -0
  98. package/src/components/AlertBanner/AlertBanner.tsx +90 -0
  99. package/src/components/AlertBanner/index.ts +11 -0
  100. package/src/components/Breadcrumbs/Breadcrumbs.css +60 -0
  101. package/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +195 -0
  102. package/src/components/Breadcrumbs/Breadcrumbs.tsx +71 -0
  103. package/src/components/Breadcrumbs/index.ts +11 -0
  104. package/src/components/Button/Button.css +213 -0
  105. package/src/components/Button/Button.mdx +133 -0
  106. package/src/components/Button/Button.stories.tsx +398 -0
  107. package/src/components/Button/Button.tsx +121 -0
  108. package/src/components/Button/index.ts +11 -0
  109. package/src/components/Card/Card.css +34 -0
  110. package/src/components/Card/Card.stories.tsx +76 -0
  111. package/src/components/Card/Card.tsx +34 -0
  112. package/src/components/Card/index.ts +10 -0
  113. package/src/components/CartItem/CartItem.css +509 -0
  114. package/src/components/CartItem/CartItem.stories.tsx +628 -0
  115. package/src/components/CartItem/CartItem.tsx +467 -0
  116. package/src/components/CartItem/CartItemSkeleton.tsx +38 -0
  117. package/src/components/CartItem/index.ts +12 -0
  118. package/src/components/CartList/CartList.css +35 -0
  119. package/src/components/CartList/CartList.stories.tsx +111 -0
  120. package/src/components/CartList/CartList.tsx +40 -0
  121. package/src/components/CartList/index.ts +11 -0
  122. package/src/components/Checkbox/Checkbox.css +255 -0
  123. package/src/components/Checkbox/Checkbox.stories.tsx +290 -0
  124. package/src/components/Checkbox/Checkbox.tsx +138 -0
  125. package/src/components/Checkbox/index.ts +10 -0
  126. package/src/components/ColorSwatch/ColorSwatch.css +132 -0
  127. package/src/components/ColorSwatch/ColorSwatch.stories.tsx +274 -0
  128. package/src/components/ColorSwatch/ColorSwatch.tsx +127 -0
  129. package/src/components/ColorSwatch/index.ts +11 -0
  130. package/src/components/ContentGrid/ContentGrid.css +54 -0
  131. package/src/components/ContentGrid/ContentGrid.stories.tsx +137 -0
  132. package/src/components/ContentGrid/ContentGrid.tsx +57 -0
  133. package/src/components/ContentGrid/index.ts +11 -0
  134. package/src/components/Divider/Divider.css +22 -0
  135. package/src/components/Divider/Divider.stories.tsx +62 -0
  136. package/src/components/Divider/Divider.tsx +33 -0
  137. package/src/components/Divider/index.ts +11 -0
  138. package/src/components/Field/Field.css +83 -0
  139. package/src/components/Field/Field.stories.tsx +238 -0
  140. package/src/components/Field/Field.tsx +84 -0
  141. package/src/components/Field/index.ts +10 -0
  142. package/src/components/Header/Header.css +56 -0
  143. package/src/components/Header/Header.stories.tsx +180 -0
  144. package/src/components/Header/Header.tsx +81 -0
  145. package/src/components/Header/index.ts +11 -0
  146. package/src/components/Icon/Icon.css +26 -0
  147. package/src/components/Icon/Icon.stories.helpers.jsx +21 -0
  148. package/src/components/Icon/Icon.stories.tsx +98 -0
  149. package/src/components/Icon/Icon.tsx +112 -0
  150. package/src/components/Icon/index.ts +10 -0
  151. package/src/components/IllustratedMessage/IllustratedMessage.css +61 -0
  152. package/src/components/IllustratedMessage/IllustratedMessage.stories.tsx +126 -0
  153. package/src/components/IllustratedMessage/IllustratedMessage.tsx +78 -0
  154. package/src/components/IllustratedMessage/index.ts +11 -0
  155. package/src/components/Image/Image.css +52 -0
  156. package/src/components/Image/Image.stories.tsx +89 -0
  157. package/src/components/Image/Image.tsx +66 -0
  158. package/src/components/Image/index.ts +10 -0
  159. package/src/components/ImageSwatch/ImageSwatch.css +154 -0
  160. package/src/components/ImageSwatch/ImageSwatch.stories.tsx +310 -0
  161. package/src/components/ImageSwatch/ImageSwatch.tsx +123 -0
  162. package/src/components/ImageSwatch/index.ts +11 -0
  163. package/src/components/InLineAlert/InLineAlert.css +116 -0
  164. package/src/components/InLineAlert/InLineAlert.stories.tsx +326 -0
  165. package/src/components/InLineAlert/InLineAlert.tsx +128 -0
  166. package/src/components/InLineAlert/index.ts +11 -0
  167. package/src/components/Incrementer/Incrementer.css +165 -0
  168. package/src/components/Incrementer/Incrementer.stories.tsx +172 -0
  169. package/src/components/Incrementer/Incrementer.tsx +192 -0
  170. package/src/components/Incrementer/index.ts +10 -0
  171. package/src/components/Input/Input.css +304 -0
  172. package/src/components/Input/Input.stories.tsx +155 -0
  173. package/src/components/Input/Input.tsx +166 -0
  174. package/src/components/Input/index.ts +11 -0
  175. package/src/components/InputDate/InputDate.css +56 -0
  176. package/src/components/InputDate/InputDate.stories.tsx +117 -0
  177. package/src/components/InputDate/InputDate.tsx +120 -0
  178. package/src/components/InputDate/index.ts +11 -0
  179. package/src/components/InputPassword/InputPassword.css +31 -0
  180. package/src/components/InputPassword/InputPassword.stories.tsx +148 -0
  181. package/src/components/InputPassword/InputPassword.tsx +135 -0
  182. package/src/components/InputPassword/PasswordStatusIndicator/PasswordStatusIndicator.css +31 -0
  183. package/src/components/InputPassword/PasswordStatusIndicator/PasswordStatusIndicator.tsx +96 -0
  184. package/src/components/InputPassword/PasswordStatusIndicator/index.ts +11 -0
  185. package/src/components/InputPassword/index.ts +11 -0
  186. package/src/components/Modal/Modal.css +125 -0
  187. package/src/components/Modal/Modal.stories.tsx +250 -0
  188. package/src/components/Modal/Modal.tsx +157 -0
  189. package/src/components/Modal/index.ts +10 -0
  190. package/src/components/Pagination/Pagination.css +95 -0
  191. package/src/components/Pagination/Pagination.stories.tsx +117 -0
  192. package/src/components/Pagination/Pagination.tsx +149 -0
  193. package/src/components/Pagination/index.ts +11 -0
  194. package/src/components/Picker/Picker.css +220 -0
  195. package/src/components/Picker/Picker.stories.tsx +318 -0
  196. package/src/components/Picker/Picker.tsx +203 -0
  197. package/src/components/Picker/index.ts +10 -0
  198. package/src/components/Price/Price.css +57 -0
  199. package/src/components/Price/Price.stories.tsx +110 -0
  200. package/src/components/Price/Price.tsx +75 -0
  201. package/src/components/Price/index.ts +10 -0
  202. package/src/components/PriceRange/PriceRange.css +66 -0
  203. package/src/components/PriceRange/PriceRange.stories.tsx +240 -0
  204. package/src/components/PriceRange/PriceRange.tsx +248 -0
  205. package/src/components/PriceRange/index.ts +11 -0
  206. package/src/components/ProgressSpinner/ProgressSpinner.css +91 -0
  207. package/src/components/ProgressSpinner/ProgressSpinner.stories.tsx +300 -0
  208. package/src/components/ProgressSpinner/ProgressSpinner.tsx +86 -0
  209. package/src/components/ProgressSpinner/index.ts +11 -0
  210. package/src/components/RadioButton/RadioButton.css +134 -0
  211. package/src/components/RadioButton/RadioButton.stories.tsx +126 -0
  212. package/src/components/RadioButton/RadioButton.tsx +86 -0
  213. package/src/components/RadioButton/index.ts +11 -0
  214. package/src/components/Skeleton/Skeleton.css +145 -0
  215. package/src/components/Skeleton/Skeleton.stories.tsx +265 -0
  216. package/src/components/Skeleton/Skeleton.tsx +133 -0
  217. package/src/components/Skeleton/index.ts +10 -0
  218. package/src/components/Tag/Tag.css +26 -0
  219. package/src/components/Tag/Tag.stories.tsx +103 -0
  220. package/src/components/Tag/Tag.tsx +38 -0
  221. package/src/components/Tag/index.ts +11 -0
  222. package/src/components/TextArea/TextArea.css +140 -0
  223. package/src/components/TextArea/TextArea.stories.tsx +130 -0
  224. package/src/components/TextArea/TextArea.tsx +89 -0
  225. package/src/components/TextArea/index.ts +11 -0
  226. package/src/components/TextSwatch/TextSwatch.css +152 -0
  227. package/src/components/TextSwatch/TextSwatch.stories.tsx +277 -0
  228. package/src/components/TextSwatch/TextSwatch.tsx +131 -0
  229. package/src/components/TextSwatch/index.ts +11 -0
  230. package/src/components/ToggleButton/ToggleButton.css +95 -0
  231. package/src/components/ToggleButton/ToggleButton.stories.tsx +190 -0
  232. package/src/components/ToggleButton/ToggleButton.tsx +75 -0
  233. package/src/components/ToggleButton/index.ts +11 -0
  234. package/src/components/UIProvider/UIProvider.css +140 -0
  235. package/src/components/UIProvider/UIProvider.tsx +61 -0
  236. package/src/components/UIProvider/debugger.css +47 -0
  237. package/src/components/UIProvider/index.ts +10 -0
  238. package/src/components/UIProvider/normalize.css +26 -0
  239. package/src/components/index.ts +49 -0
  240. package/src/docs/API/event-bus.mdx +52 -0
  241. package/src/docs/API/graphql.mdx +214 -0
  242. package/src/docs/API/initializer.mdx +119 -0
  243. package/src/docs/API/render.mdx +125 -0
  244. package/src/docs/Design/colors.mdx +202 -0
  245. package/src/docs/Design/designBlocks.jsx +87 -0
  246. package/src/docs/Design/getTokenData.ts +28 -0
  247. package/src/docs/Design/grid.mdx +365 -0
  248. package/src/docs/Design/overview.mdx +69 -0
  249. package/src/docs/Design/shapes.mdx +100 -0
  250. package/src/docs/Design/spacing.mdx +22 -0
  251. package/src/docs/Design/typography.mdx +126 -0
  252. package/src/docs/Utilities/classList.mdx +52 -0
  253. package/src/docs/Utilities/debounce.mdx +49 -0
  254. package/src/docs/Utilities/deepmerge.mdx +12 -0
  255. package/src/docs/Utilities/getFormErrors.mdx +41 -0
  256. package/src/docs/Utilities/getFormValues.mdx +38 -0
  257. package/src/docs/assets/Banner.png +0 -0
  258. package/src/docs/assets/Colors.png +0 -0
  259. package/src/docs/assets/DropinBanner.png +0 -0
  260. package/src/docs/assets/ShapeStyles.png +0 -0
  261. package/src/docs/assets/Spacing.png +0 -0
  262. package/src/docs/assets/Typography.png +0 -0
  263. package/src/docs/cli-usage.mdx +181 -0
  264. package/src/docs/components/overview.mdx +124 -0
  265. package/src/docs/quick-start.mdx +245 -0
  266. package/src/docs/slots.mdx +211 -0
  267. package/src/docs/welcome.mdx +52 -0
  268. package/src/i18n/en_US.json +146 -0
  269. package/src/i18n/index.ts +26 -0
  270. package/src/icons/Add.svg +9 -0
  271. package/src/icons/AddressBook.svg +3 -0
  272. package/src/icons/Bulk.svg +24 -0
  273. package/src/icons/Burger.svg +5 -0
  274. package/src/icons/Card.svg +7 -0
  275. package/src/icons/Cart.svg +11 -0
  276. package/src/icons/Check.svg +8 -0
  277. package/src/icons/CheckWithCircle.svg +4 -0
  278. package/src/icons/ChevronDown.svg +3 -0
  279. package/src/icons/ChevronRight.svg +8 -0
  280. package/src/icons/ChevronUp.svg +3 -0
  281. package/src/icons/Close.svg +4 -0
  282. package/src/icons/Coupon.svg +3 -0
  283. package/src/icons/Date.svg +4 -0
  284. package/src/icons/Delivery.svg +11 -0
  285. package/src/icons/EmptyBox.svg +3 -0
  286. package/src/icons/Eye.svg +3 -0
  287. package/src/icons/EyeClose.svg +3 -0
  288. package/src/icons/Gift.svg +3 -0
  289. package/src/icons/GiftCard.svg +3 -0
  290. package/src/icons/Heart.svg +3 -0
  291. package/src/icons/HeartFilled.svg +3 -0
  292. package/src/icons/InfoFilled.svg +3 -0
  293. package/src/icons/Locker.svg +11 -0
  294. package/src/icons/Minus.svg +3 -0
  295. package/src/icons/Order.svg +6 -0
  296. package/src/icons/OrderError.svg +15 -0
  297. package/src/icons/OrderSuccess.svg +15 -0
  298. package/src/icons/PaymentError.svg +16 -0
  299. package/src/icons/Placeholder.svg +3 -0
  300. package/src/icons/PlaceholderFilled.svg +4 -0
  301. package/src/icons/Search.svg +9 -0
  302. package/src/icons/SearchFilled.svg +10 -0
  303. package/src/icons/Sort.svg +12 -0
  304. package/src/icons/Star.svg +8 -0
  305. package/src/icons/Trash.svg +7 -0
  306. package/src/icons/User.svg +5 -0
  307. package/src/icons/View.svg +14 -0
  308. package/src/icons/Wallet.svg +6 -0
  309. package/src/icons/Warning.svg +12 -0
  310. package/src/icons/WarningFilled.svg +3 -0
  311. package/src/icons/WarningWithCircle.svg +4 -0
  312. package/src/icons/index.ts +42 -0
  313. package/src/lib/classes.ts +34 -0
  314. package/src/lib/config.ts +24 -0
  315. package/src/lib/debounce.ts +16 -0
  316. package/src/lib/deepmerge.ts +45 -0
  317. package/src/lib/deviceUtils.ts +16 -0
  318. package/src/lib/form-values.ts +31 -0
  319. package/src/lib/i18n.ts +18 -0
  320. package/src/lib/image-params-keymap.ts +36 -0
  321. package/src/lib/index.ts +24 -0
  322. package/src/lib/initializer.ts +134 -0
  323. package/src/lib/is-number.ts +12 -0
  324. package/src/lib/render.tsx +138 -0
  325. package/src/lib/resolve-image.ts +101 -0
  326. package/src/lib/signals.ts +11 -0
  327. package/src/lib/slot.tsx +434 -0
  328. package/src/lib/tests.tsx +47 -0
  329. package/src/lib/types.ts +16 -0
  330. package/src/lib/vcomponent.tsx +42 -0
  331. package/static/assets/images/Card.png +0 -0
  332. package/static/assets/images/example.jpg +0 -0
  333. package/static/assets/images/index.ts +11 -0
  334. package/static/dropin.png +0 -0
  335. package/static/favicon.svg +14 -0
  336. package/storybook-stories.js +21 -0
  337. package/tests/__mocks__/browserMocks.ts +28 -0
  338. package/tests/__mocks__/fileMocks.ts +12 -0
  339. package/tests/__mocks__/styleMock.ts +0 -0
  340. package/types/icons.d.ts +18 -0
@@ -0,0 +1,152 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ /* https://cssguidelin.es/#bem-like-naming */
11
+
12
+ .dropin-text-swatch__container input[type='radio'],
13
+ .dropin-text-swatch__container input[type='checkbox'] {
14
+ opacity: 0;
15
+ position: absolute;
16
+ width: 0;
17
+ }
18
+
19
+ .dropin-text-swatch__container label {
20
+ display: inline-block;
21
+ background-color: var(--color-neutral-200);
22
+ color: var(--color-neutral-800);
23
+ border: var(--shape-border-width-1) solid var(--color-neutral-400);
24
+ padding: 6px var(--spacing-small);
25
+ border-radius: var(--shape-border-radius-1);
26
+ box-sizing: border-box;
27
+ align-items: center;
28
+ justify-content: center;
29
+ font: var(--type-body-1-strong-font);
30
+ position: relative;
31
+ display: block;
32
+ overflow: hidden;
33
+ text-overflow: ellipsis;
34
+ white-space: nowrap;
35
+ }
36
+
37
+ .dropin-text-swatch__container label:hover {
38
+ color: var(--color-neutral-900);
39
+ }
40
+
41
+ .dropin-text-swatch__container
42
+ input[type='radio']:checked
43
+ + .dropin-text-swatch__label,
44
+ .dropin-text-swatch__container
45
+ input[type='checkbox']:checked
46
+ + .dropin-text-swatch__label,
47
+ .dropin-text-swatch--selected {
48
+ background-color: var(--color-neutral-50);
49
+ box-shadow: 0 0 0 var(--shape-border-width-1) var(--color-neutral-900);
50
+ }
51
+
52
+ .dropin-text-swatch__container input[type='radio']:focus-visible + label,
53
+ .dropin-text-swatch__container input[type='checkbox']:focus-visible + label {
54
+ background-color: var(--color-neutral-200);
55
+ border: var(--shape-border-width-3) solid var(--color-neutral-800);
56
+ outline: solid var(--shape-border-width-4) var(--color-neutral-400);
57
+ }
58
+
59
+ .dropin-text-swatch__container input[type='radio']:checked + label:active,
60
+ .dropin-text-swatch__container input[type='checkbox']:checked + label:active,
61
+ .dropin-text-swatch--selected {
62
+ background-color: var(--color-neutral-200);
63
+ box-shadow: 0 0 0 var(--shape-border-width-3) var(--color-neutral-900),
64
+ 0 0 0 6px var(--color-neutral-400);
65
+ }
66
+
67
+ .dropin-text-swatch__container input[type='radio']:active + label,
68
+ .dropin-text-swatch__container input[type='radio']:checked + label:active,
69
+ .dropin-text-swatch__container
70
+ input[type='radio']:checked
71
+ + label:hover:not(:focus-visible),
72
+ .dropin-text-swatch__container input[type='checkbox']:active + label,
73
+ .dropin-text-swatch__container input[type='checkbox']:checked + label:active,
74
+ .dropin-text-swatch__container
75
+ input[type='checkbox']:checked
76
+ + label:hover:not(:focus-visible) {
77
+ border: var(--shape-border-width-1) solid var(--color-neutral-500);
78
+ color: var(--color-neutral-900);
79
+ outline: none;
80
+ }
81
+
82
+ .dropin-text-swatch__container input[type='radio']:disabled + label,
83
+ .dropin-text-swatch__container input[type='checkbox']:disabled + label,
84
+ .dropin-text-swatch--disabled,
85
+ .dropin-text-swatch__container
86
+ input[type='radio']:disabled:focus-visible
87
+ + label,
88
+ .dropin-text-swatch__container
89
+ input[type='checkbox']:disabled:focus-visible
90
+ + label {
91
+ background-color: var(--color-neutral-300);
92
+ color: var(--color-neutral-500);
93
+ pointer-events: none;
94
+ border: var(--shape-border-width-1) solid var(--color-neutral-500);
95
+ outline: none;
96
+ }
97
+
98
+ .dropin-text-swatch__label--out-of-stock {
99
+ background: linear-gradient(
100
+ to top left,
101
+ rgba(0, 0, 0, 0) 0%,
102
+ rgba(0, 0, 0, 0) calc(50% - 0.8px),
103
+ var(--color-neutral-700) 50%,
104
+ rgba(0, 0, 0, 0) calc(50% + 0.8px),
105
+ rgba(0, 0, 0, 0) 100%
106
+ ),
107
+ var(--color-neutral-200);
108
+ }
109
+
110
+ .dropin-text-swatch__container input[type='radio']:not(:disabled) + label,
111
+ .dropin-text-swatch__container input[type='checkbox']:not(:disabled) + label {
112
+ cursor: pointer;
113
+ }
114
+
115
+ [data-tooltip] {
116
+ position: relative;
117
+ }
118
+
119
+ [data-tooltip]:after {
120
+ display: none;
121
+ content: attr(data-tooltip);
122
+ position: absolute;
123
+ bottom: 100%;
124
+ left: 0px;
125
+ background-color: var(--color-neutral-50);
126
+ color: var(--color-neutral-800);
127
+ border: var(--shape-border-width-1) solid var(--color-neutral-400);
128
+ padding: 6px var(--spacing-small);
129
+ border-radius: var(--shape-border-radius-1);
130
+ white-space: nowrap;
131
+ z-index: 1000;
132
+ font: var(--type-body-1-strong-font);
133
+ margin-bottom: var(--spacing-xxsmall);
134
+ -webkit-border-radius: var(--shape-border-radius-1);
135
+ -moz-border-radius: var(--shape-border-radius-1);
136
+ }
137
+
138
+ [data-tooltip]:hover:after {
139
+ display: block;
140
+ }
141
+
142
+ /* Medium (portrait tablets and large phones, 768px and up) */
143
+ /* @media only screen and (min-width: 768px) { } */
144
+
145
+ /* Large (landscape tablets, 1024px and up) */
146
+ /* @media only screen and (min-width: 1024px) { } */
147
+
148
+ /* XLarge (laptops/desktops, 1366px and up) */
149
+ /* @media only screen and (min-width: 1366px) { } */
150
+
151
+ /* XXlarge (large laptops and desktops, 1920px and up) */
152
+ /* @media only screen and (min-width: 1920px) { } */
@@ -0,0 +1,277 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ // https://storybook.js.org/docs/7.0/preact/writing-stories/introduction
11
+ /* eslint-disable react/no-danger */
12
+ import type { Meta, StoryObj } from '@storybook/preact';
13
+ import { action } from '@storybook/addon-actions';
14
+ import { expect, userEvent, within } from '@storybook/test';
15
+ import {
16
+ TextSwatch,
17
+ TextSwatchProps,
18
+ } from '@adobe-commerce/elsie/components/TextSwatch';
19
+
20
+ /**
21
+ * Use Text Swatches to display text selections, like sizes or categories.
22
+ */
23
+ const meta: Meta<TextSwatchProps> = {
24
+ title: 'Components/TextSwatch',
25
+ component: TextSwatch,
26
+ argTypes: {
27
+ name: {
28
+ description: 'Field name (used for mapping the value in a form)',
29
+ type: {
30
+ required: false,
31
+ name: 'string',
32
+ },
33
+ },
34
+
35
+ label: {
36
+ description: 'Field label',
37
+ type: {
38
+ required: true,
39
+ name: 'string',
40
+ },
41
+ },
42
+ groupAriaLabel: {
43
+ description: 'Label name for the swatch group',
44
+ type: {
45
+ required: true,
46
+ name: 'string',
47
+ },
48
+ },
49
+ id: {
50
+ description: 'Field id',
51
+ type: {
52
+ required: true,
53
+ name: 'string',
54
+ },
55
+ },
56
+ value: {
57
+ description: 'Field value',
58
+ type: {
59
+ required: false,
60
+ name: 'string',
61
+ },
62
+ },
63
+ disabled: {
64
+ description: 'Whether or not the text swatch is disabled',
65
+ type: {
66
+ required: false,
67
+ name: 'boolean',
68
+ },
69
+ },
70
+ selected: {
71
+ description: 'Whether or not the text swatch is active',
72
+ type: {
73
+ required: false,
74
+ name: 'boolean',
75
+ },
76
+ },
77
+ multi: {
78
+ description: 'Whether or not the text swatch allows multiple selection',
79
+ type: {
80
+ required: false,
81
+ name: 'boolean',
82
+ },
83
+ },
84
+ outOfStock: {
85
+ description: 'Whether or not the text swatch is out of stock',
86
+ type: {
87
+ required: false,
88
+ name: 'boolean',
89
+ },
90
+ },
91
+ onValue: {
92
+ description: 'Function to handle value changes',
93
+ type: {
94
+ required: false,
95
+ name: 'function',
96
+ },
97
+ },
98
+ onUpdateError: {
99
+ description: 'Function to handle error updates',
100
+ type: {
101
+ required: false,
102
+ name: 'function',
103
+ },
104
+ },
105
+ },
106
+ };
107
+
108
+ export default meta;
109
+
110
+ type Story = StoryObj<TextSwatchProps>;
111
+
112
+ /**
113
+ * ```ts
114
+ * import { TextSwatch } from '@adobe-commerce/elsie/components/TextSwatch';
115
+ * ```
116
+ */
117
+
118
+ export const DefaultTextSwatch: Story = {
119
+ name: 'Text Swatch',
120
+ args: {
121
+ name: 'textSwatchField',
122
+ label: 'Option',
123
+ groupAriaLabel: 'Text Swatches',
124
+ id: 'mediumOption',
125
+ value: 'option',
126
+ selected: false,
127
+ disabled: false,
128
+ outOfStock: false,
129
+ onValue: action('onValue'),
130
+ },
131
+ play: async ({ canvasElement }) => {
132
+ const canvas = within(canvasElement);
133
+ const textSwatch = await canvas.findByRole('radio');
134
+ const labelElement = document.querySelector(
135
+ '.dropin-text-swatch__label'
136
+ ) as HTMLElement;
137
+ expect(labelElement).toBeVisible();
138
+ await expect(textSwatch).not.toBeChecked();
139
+ },
140
+ };
141
+
142
+ const swatchStyle = `
143
+ .dropin-text-swatch__label {
144
+ max-width: 100px;
145
+ }
146
+ `;
147
+
148
+ export const TextSwatchWithLongText: Story = {
149
+ name: 'Long Text Swatch',
150
+ render: (args) => (
151
+ <div>
152
+ <style dangerouslySetInnerHTML={{ __html: swatchStyle }} />
153
+ <TextSwatch {...args} />
154
+ </div>
155
+ ),
156
+ args: {
157
+ name: 'textSwatchField',
158
+ label: 'Long Text Swatch',
159
+ groupAriaLabel: 'Text Swatches',
160
+ id: 'mediumOption',
161
+ value: 'long text swatch',
162
+ selected: false,
163
+ disabled: false,
164
+ outOfStock: false,
165
+ onValue: action('onValue'),
166
+ },
167
+ play: async ({ canvasElement }) => {
168
+ const canvas = within(canvasElement);
169
+ const textSwatch = await canvas.findByRole('radio');
170
+ const labelElement = document.querySelector(
171
+ '.dropin-text-swatch__label'
172
+ ) as HTMLElement;
173
+ expect(labelElement).toBeVisible();
174
+
175
+ userEvent.hover(textSwatch);
176
+
177
+ // Without this wait test failing
178
+ await new Promise((resolve) => setTimeout(resolve, 500));
179
+
180
+ const divWithTooltip = document.querySelector(
181
+ 'div[data-tooltip]'
182
+ ) as HTMLElement;
183
+
184
+ expect(divWithTooltip.getAttribute('data-tooltip')).toBe(
185
+ 'Long Text Swatch'
186
+ );
187
+ },
188
+ };
189
+
190
+ export const SelectedTextSwatch: Story = {
191
+ args: {
192
+ name: 'textSwatchField',
193
+ label: 'Option',
194
+ groupAriaLabel: 'Text Swatches',
195
+ id: 'mediumOption',
196
+ value: 'option',
197
+ selected: true,
198
+ disabled: false,
199
+ outOfStock: false,
200
+ onValue: action('onValue'),
201
+ },
202
+ play: async ({ canvasElement }) => {
203
+ const canvas = within(canvasElement);
204
+ const textSwatch = await canvas.findByRole('radio');
205
+ const labelElement = document.querySelector(
206
+ '.dropin-text-swatch__label'
207
+ ) as HTMLElement;
208
+ expect(labelElement).toBeVisible();
209
+ await expect(textSwatch).toBeChecked();
210
+ },
211
+ };
212
+ export const DisabledTextSwatch: Story = {
213
+ args: {
214
+ name: 'textSwatchField',
215
+ label: 'Option',
216
+ groupAriaLabel: 'Text Swatches',
217
+ id: 'mediumOption',
218
+ value: 'option',
219
+ selected: false,
220
+ disabled: true,
221
+ outOfStock: false,
222
+ onValue: action('onValue'),
223
+ },
224
+ play: async ({ canvasElement }) => {
225
+ const canvas = within(canvasElement);
226
+ await expect(await canvas.findByRole('radio')).toBeDisabled();
227
+ },
228
+ };
229
+
230
+ export const OutOfStockTextSwatch: Story = {
231
+ args: {
232
+ name: 'textSwatchField',
233
+ label: 'Option',
234
+ groupAriaLabel: 'Text Swatches',
235
+ id: 'mediumOption',
236
+ value: 'option',
237
+ selected: false,
238
+ disabled: false,
239
+ outOfStock: true,
240
+ onValue: action('onValue'),
241
+ },
242
+ };
243
+
244
+ export const SelectedOutOfStockTextSwatch: Story = {
245
+ args: {
246
+ name: 'textSwatchField',
247
+ label: 'Option',
248
+ groupAriaLabel: 'Text Swatches',
249
+ id: 'mediumOption',
250
+ value: 'option',
251
+ selected: true,
252
+ disabled: false,
253
+ outOfStock: true,
254
+ onValue: action('onValue'),
255
+ },
256
+ };
257
+
258
+ export const MultiTextSwatch: Story = {
259
+ args: {
260
+ name: 'multiTextSwatchField',
261
+ label: 'Option',
262
+ id: 'multiOption',
263
+ value: 'option',
264
+ selected: false,
265
+ disabled: false,
266
+ outOfStock: false,
267
+ multi: true,
268
+ onValue: action('onValue'),
269
+ },
270
+ render: (args) => (
271
+ <div style="display: flex; flex-wrap:wrap; gap: 25px">
272
+ <TextSwatch {...args} id={'optionS'} value={'S'} label={'S'} />
273
+ <TextSwatch {...args} id={'optionM'} value={'M'} label={'M'} />
274
+ <TextSwatch {...args} id={'optionL'} value={'L'} label={'L'} />
275
+ </div>
276
+ ),
277
+ };
@@ -0,0 +1,131 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ import { FunctionComponent } from 'preact';
11
+ import {
12
+ HTMLAttributes,
13
+ useState,
14
+ useEffect,
15
+ useRef,
16
+ useCallback,
17
+ } from 'preact/compat';
18
+ import { classes } from '@adobe-commerce/elsie/lib';
19
+ import '@adobe-commerce/elsie/components/TextSwatch/TextSwatch.css';
20
+ import { useText } from '@adobe-commerce/elsie/i18n';
21
+
22
+ export interface TextSwatchProps
23
+ extends Omit<HTMLAttributes<HTMLInputElement>, 'label'> {
24
+ name?: string;
25
+ label: string;
26
+ groupAriaLabel?: string;
27
+ value?: string;
28
+ id: string;
29
+ disabled?: boolean;
30
+ selected?: boolean;
31
+ outOfStock?: boolean;
32
+ multi?: boolean;
33
+ onValue?: (value: any) => void;
34
+ onUpdateError?: (error: Error) => void;
35
+ }
36
+
37
+ export const TextSwatch: FunctionComponent<TextSwatchProps> = ({
38
+ className,
39
+ name,
40
+ value,
41
+ label,
42
+ groupAriaLabel,
43
+ id,
44
+ disabled = false,
45
+ selected = false,
46
+ outOfStock = false,
47
+ multi = false,
48
+ onValue,
49
+ onUpdateError,
50
+ ...props
51
+ }) => {
52
+ // i18n
53
+ const outOfStockLabel = useText('Dropin.Swatches.outOfStock.label').label;
54
+ const selectedLabel = useText('Dropin.Swatches.selected.label').label;
55
+ const swatchLabel = useText('Dropin.Swatches.swatch.label').label;
56
+
57
+ const [isOverflowing, setIsOverflowing] = useState(false);
58
+ const spanRef = useRef<HTMLLabelElement>(null);
59
+
60
+ const onValueHandler = useCallback(
61
+ async (newValue: any) => {
62
+ if (onValue) {
63
+ try {
64
+ await onValue(newValue);
65
+ } catch (e) {
66
+ if (onUpdateError) {
67
+ onUpdateError(e as Error);
68
+ }
69
+ }
70
+ }
71
+ },
72
+ [onValue, onUpdateError]
73
+ );
74
+
75
+ const handleOnValue = (e: Event) => {
76
+ const input = e.target as HTMLInputElement;
77
+
78
+ onValueHandler(input.value);
79
+ };
80
+
81
+ const handleAriaLabel = () => {
82
+ if (outOfStock) return `${groupAriaLabel}: ${label} ${outOfStockLabel}`;
83
+ if (selected) return `${groupAriaLabel}: ${label} ${selectedLabel}`;
84
+ return `${groupAriaLabel}: ${label} ${swatchLabel}`;
85
+ };
86
+
87
+ useEffect(() => {
88
+ if (
89
+ spanRef.current &&
90
+ spanRef.current.scrollWidth > spanRef.current.clientWidth
91
+ ) {
92
+ setIsOverflowing(true);
93
+ }
94
+ }, [label]);
95
+
96
+ return (
97
+ <div
98
+ className="dropin-text-swatch__container"
99
+ {...(isOverflowing ? { 'data-tooltip': label } : {})}
100
+ >
101
+ <input
102
+ type={multi ? 'checkbox' : 'radio'}
103
+ name={name}
104
+ id={id}
105
+ value={value}
106
+ aria-label={handleAriaLabel()}
107
+ checked={selected}
108
+ disabled={disabled}
109
+ onChange={handleOnValue}
110
+ {...props}
111
+ className={classes([
112
+ 'dropin-text-swatch',
113
+ ['dropin-text-swatch--selected', selected],
114
+ ['dropin-text-swatch--disabled', disabled],
115
+ className,
116
+ ])}
117
+ />
118
+ <label
119
+ htmlFor={id}
120
+ ref={spanRef}
121
+ className={classes([
122
+ 'dropin-text-swatch__label',
123
+ ['dropin-text-swatch__label--out-of-stock', outOfStock],
124
+ className,
125
+ ])}
126
+ >
127
+ {label}
128
+ </label>
129
+ </div>
130
+ );
131
+ };
@@ -0,0 +1,11 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ export * from '@adobe-commerce/elsie/components/TextSwatch/TextSwatch';
11
+ export { TextSwatch as default } from '@adobe-commerce/elsie/components/TextSwatch/TextSwatch';
@@ -0,0 +1,95 @@
1
+ /********************************************************************
2
+ * Copyright 2024 Adobe
3
+ * All Rights Reserved.
4
+ *
5
+ * NOTICE: Adobe permits you to use, modify, and distribute this
6
+ * file in accordance with the terms of the Adobe license agreement
7
+ * accompanying it.
8
+ *******************************************************************/
9
+
10
+ /* https://cssguidelin.es/#bem-like-naming */
11
+
12
+ /* Container */
13
+ .dropin-toggle-button {
14
+ display: block;
15
+ position: relative;
16
+ width: 100%;
17
+ }
18
+
19
+ /* Action button */
20
+ .dropin-toggle-button__actionButton {
21
+ cursor: pointer;
22
+ background-color: var(--color-neutral-200);
23
+ border: var(--shape-border-width-1) solid var(--color-neutral-400);
24
+ border-radius: var(--shape-border-radius-1);
25
+ font: var(--type-body-2-strong-font);
26
+ letter-spacing: var(--type-body-2-strong-letter-spacing);
27
+ padding: var(--spacing-medium);
28
+ align-items: center;
29
+ display: grid;
30
+ }
31
+
32
+ .dropin-toggle-button__selected .dropin-toggle-button__actionButton {
33
+ background-color: var(--color-neutral-50);
34
+ border: var(--shape-border-width-1) solid var(--color-neutral-800);
35
+ }
36
+
37
+ .dropin-toggle-button:has(input:focus-visible) {
38
+ outline: 0 none;
39
+ box-shadow: 0 0 0 var(--shape-icon-stroke-4) var(--color-neutral-400);
40
+ -webkit-box-shadow: 0 0 0 var(--shape-icon-stroke-4) var(--color-neutral-400);
41
+ -moz-box-shadow: 0 0 0 var(--shape-icon-stroke-4) var(--color-neutral-400);
42
+ border-radius: var(--shape-border-radius-1);
43
+ }
44
+
45
+ /* Radio Button */
46
+ .dropin-toggle-button__radioButton.dropin-radio-button {
47
+ cursor: pointer;
48
+ position: absolute;
49
+ }
50
+
51
+ .dropin-toggle-button__radioButton .dropin-radio-button__label:before {
52
+ cursor: pointer;
53
+ margin-right: 0;
54
+ }
55
+
56
+ /* Disable radioButton focus-visible */
57
+ .dropin-toggle-button__radioButton .dropin-radio-button__input:focus-visible + .dropin-radio-button__label:before {
58
+ box-shadow: 0 0 0 var(--shape-border-width-1) var(--color-neutral-600);
59
+ }
60
+
61
+ /* Label */
62
+ .dropin-toggle-button__content {
63
+ color: var(--color-neutral-800);
64
+ font: var(--type-body-2-default-font);
65
+ letter-spacing: var(--type-body-2-default-letter-spacing);
66
+ display: flex;
67
+ align-items: center;
68
+ justify-content: center;
69
+ margin-left: var(--spacing-big);
70
+ cursor: pointer;
71
+ }
72
+
73
+ .dropin-toggle-button__content a {
74
+ color: var(--color-brand-500);
75
+ font: var(--type-body-2-strong-font);
76
+ letter-spacing: var(--type-body-2-strong-letter-spacing);
77
+ }
78
+
79
+ /* Icon */
80
+ .dropin-toggle-button__icon {
81
+ height: 24px;
82
+ margin-right: var(--spacing-xsmall);
83
+ }
84
+
85
+ /* Medium (portrait tablets and large phones, 768px and up) */
86
+ /* @media only screen and (min-width: 768px) { } */
87
+
88
+ /* Large (landscape tablets, 1024px and up) */
89
+ /* @media only screen and (min-width: 1024px) { } */
90
+
91
+ /* XLarge (laptops/desktops, 1366px and up) */
92
+ /* @media only screen and (min-width: 1366px) { } */
93
+
94
+ /* XXlarge (large laptops and desktops, 1920px and up) */
95
+ /* @media only screen and (min-width: 1920px) { } */