@momentum-design/components 0.0.1

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 (235) hide show
  1. package/.eslintrc.js +16 -0
  2. package/CONTRIBUTING.md +5 -0
  3. package/README.md +39 -0
  4. package/SCRIPTS.md +15 -0
  5. package/TESTING.md +38 -0
  6. package/config/api-extractor.json +33 -0
  7. package/config/custom-elements-manifest.config.js +28 -0
  8. package/config/esbuild/configs/browser.js +21 -0
  9. package/config/esbuild/configs/e2e.js +10 -0
  10. package/config/esbuild/esbuild-e2e.config.js +22 -0
  11. package/config/esbuild/esbuild.config.js +9 -0
  12. package/config/playwright/playwright.config.ts +107 -0
  13. package/config/playwright/public/index.css +43 -0
  14. package/config/playwright/public/index.html +26 -0
  15. package/config/playwright/setup/Components.page.ts +163 -0
  16. package/config/playwright/setup/constants.ts +27 -0
  17. package/config/playwright/setup/index.ts +42 -0
  18. package/config/playwright/setup/steps/accessibility.ts +9 -0
  19. package/config/playwright/setup/types.ts +5 -0
  20. package/config/playwright/setup/utils/accessibility.ts +70 -0
  21. package/config/playwright/setup/utils/visual-regression.ts +35 -0
  22. package/config/plop/actions/AddComponent.ts +21 -0
  23. package/config/plop/actions/AddToComponentExports.ts +16 -0
  24. package/config/plop/actions/AddToComponentImports.ts +16 -0
  25. package/config/plop/constants/index.ts +31 -0
  26. package/config/plop/esbuild.config.plop.js +4 -0
  27. package/config/plop/generators/component/index.ts +25 -0
  28. package/config/plop/plopfile.ts +6 -0
  29. package/config/plop/prompts/index.ts +8 -0
  30. package/config/plop/templates/add/component/index.ts.hbs +12 -0
  31. package/config/plop/templates/add/component/{{componentName}}.component.ts.hbs +22 -0
  32. package/config/plop/templates/add/component/{{componentName}}.constants.ts.hbs +5 -0
  33. package/config/plop/templates/add/component/{{componentName}}.e2e-test.ts.hbs +67 -0
  34. package/config/plop/templates/add/component/{{componentName}}.fixtures.ts.hbs +13 -0
  35. package/config/plop/templates/add/component/{{componentName}}.stories.ts.hbs +18 -0
  36. package/config/plop/templates/add/component/{{componentName}}.styles.ts.hbs +8 -0
  37. package/config/plop/tsconfig.plop.json +11 -0
  38. package/config/storybook/MomentumStorybookTheme.js +41 -0
  39. package/config/storybook/main.js +21 -0
  40. package/config/storybook/manager.js +17 -0
  41. package/config/storybook/preview.js +63 -0
  42. package/config/storybook/provider/iconProvider.js +8 -0
  43. package/config/storybook/provider/themeProvider.js +31 -0
  44. package/config/storybook/public/background-graphic.png +0 -0
  45. package/config/storybook/public/fonts/Inter.var.woff2 +0 -0
  46. package/config/storybook/public/momentum-logo.png +0 -0
  47. package/config/storybook/themes/index.js +14 -0
  48. package/config/storybook/themes/themes.css +15 -0
  49. package/data/custom-elements.json +677 -0
  50. package/dist/browser/index.js +366 -0
  51. package/dist/browser/index.js.map +7 -0
  52. package/dist/components/avatar/avatar.component.d.ts +28 -0
  53. package/dist/components/avatar/avatar.component.js +79 -0
  54. package/dist/components/avatar/avatar.constants.d.ts +7 -0
  55. package/dist/components/avatar/avatar.constants.js +14 -0
  56. package/dist/components/avatar/avatar.styles.d.ts +2 -0
  57. package/dist/components/avatar/avatar.styles.js +20 -0
  58. package/dist/components/avatar/avatar.types.d.ts +1 -0
  59. package/dist/components/avatar/avatar.types.js +2 -0
  60. package/dist/components/avatar/index.d.ts +7 -0
  61. package/dist/components/avatar/index.js +7 -0
  62. package/dist/components/badge/badge.component.d.ts +51 -0
  63. package/dist/components/badge/badge.component.js +114 -0
  64. package/dist/components/badge/badge.constants.d.ts +8 -0
  65. package/dist/components/badge/badge.constants.js +15 -0
  66. package/dist/components/badge/badge.styles.d.ts +2 -0
  67. package/dist/components/badge/badge.styles.js +26 -0
  68. package/dist/components/badge/badge.types.d.ts +1 -0
  69. package/dist/components/badge/badge.types.js +2 -0
  70. package/dist/components/badge/index.d.ts +7 -0
  71. package/dist/components/badge/index.js +7 -0
  72. package/dist/components/icon/icon.component.d.ts +63 -0
  73. package/dist/components/icon/icon.component.js +158 -0
  74. package/dist/components/icon/icon.constants.d.ts +6 -0
  75. package/dist/components/icon/icon.constants.js +12 -0
  76. package/dist/components/icon/icon.styles.d.ts +2 -0
  77. package/dist/components/icon/icon.styles.js +15 -0
  78. package/dist/components/icon/icon.utils.d.ts +2 -0
  79. package/dist/components/icon/icon.utils.js +13 -0
  80. package/dist/components/icon/index.d.ts +7 -0
  81. package/dist/components/icon/index.js +7 -0
  82. package/dist/components/iconprovider/iconprovider.component.d.ts +34 -0
  83. package/dist/components/iconprovider/iconprovider.component.js +71 -0
  84. package/dist/components/iconprovider/iconprovider.constants.d.ts +7 -0
  85. package/dist/components/iconprovider/iconprovider.constants.js +14 -0
  86. package/dist/components/iconprovider/iconprovider.context.d.ts +9 -0
  87. package/dist/components/iconprovider/iconprovider.context.js +9 -0
  88. package/dist/components/iconprovider/index.d.ts +7 -0
  89. package/dist/components/iconprovider/index.js +7 -0
  90. package/dist/components/text/fonts.styles.d.ts +1 -0
  91. package/dist/components/text/fonts.styles.js +100 -0
  92. package/dist/components/text/index.d.ts +7 -0
  93. package/dist/components/text/index.js +7 -0
  94. package/dist/components/text/text.component.d.ts +29 -0
  95. package/dist/components/text/text.component.js +41 -0
  96. package/dist/components/text/text.constants.d.ts +9 -0
  97. package/dist/components/text/text.constants.js +28 -0
  98. package/dist/components/text/text.styles.d.ts +2 -0
  99. package/dist/components/text/text.styles.js +17 -0
  100. package/dist/components/text/text.types.d.ts +1 -0
  101. package/dist/components/text/text.types.js +2 -0
  102. package/dist/components/text/text.utils.d.ts +20 -0
  103. package/dist/components/text/text.utils.js +50 -0
  104. package/dist/components/themeprovider/index.d.ts +7 -0
  105. package/dist/components/themeprovider/index.js +7 -0
  106. package/dist/components/themeprovider/themeprovider.component.d.ts +48 -0
  107. package/dist/components/themeprovider/themeprovider.component.js +86 -0
  108. package/dist/components/themeprovider/themeprovider.constants.d.ts +10 -0
  109. package/dist/components/themeprovider/themeprovider.constants.js +31 -0
  110. package/dist/components/themeprovider/themeprovider.context.d.ts +9 -0
  111. package/dist/components/themeprovider/themeprovider.context.js +13 -0
  112. package/dist/components/themeprovider/themeprovider.styles.d.ts +2 -0
  113. package/dist/components/themeprovider/themeprovider.styles.js +13 -0
  114. package/dist/components/themeprovider/themeprovider.types.d.ts +5 -0
  115. package/dist/components/themeprovider/themeprovider.types.js +2 -0
  116. package/dist/components/themeprovider/themeprovider.utils.d.ts +9 -0
  117. package/dist/components/themeprovider/themeprovider.utils.js +10 -0
  118. package/dist/index.d.ts +8 -0
  119. package/dist/index.js +19 -0
  120. package/dist/models/component/component.component.d.ts +38 -0
  121. package/dist/models/component/component.component.js +45 -0
  122. package/dist/models/component/component.types.d.ts +15 -0
  123. package/dist/models/component/component.types.js +2 -0
  124. package/dist/models/component/index.d.ts +3 -0
  125. package/dist/models/component/index.js +5 -0
  126. package/dist/models/index.d.ts +4 -0
  127. package/dist/models/index.js +8 -0
  128. package/dist/models/provider/index.d.ts +2 -0
  129. package/dist/models/provider/index.js +5 -0
  130. package/dist/models/provider/provider.component.d.ts +70 -0
  131. package/dist/models/provider/provider.component.js +56 -0
  132. package/dist/models/provider/provider.styles.d.ts +2 -0
  133. package/dist/models/provider/provider.styles.js +14 -0
  134. package/dist/utils/provider/index.d.ts +13 -0
  135. package/dist/utils/provider/index.js +14 -0
  136. package/dist/utils/styles/index.d.ts +2 -0
  137. package/dist/utils/styles/index.js +14 -0
  138. package/dist/utils/tag-name/constants.d.ts +7 -0
  139. package/dist/utils/tag-name/constants.js +10 -0
  140. package/dist/utils/tag-name/index.d.ts +4 -0
  141. package/dist/utils/tag-name/index.js +10 -0
  142. package/dist/utils/types.d.ts +1 -0
  143. package/dist/utils/types.js +2 -0
  144. package/jest.config.js +3 -0
  145. package/package.json +78 -0
  146. package/scripts/copyFonts.js +31 -0
  147. package/scripts/copyIcons.js +31 -0
  148. package/scripts/copyTokens.js +24 -0
  149. package/src/components/avatar/__screenshots__/mdc-avatar.png +0 -0
  150. package/src/components/avatar/avatar.component.ts +74 -0
  151. package/src/components/avatar/avatar.constants.ts +12 -0
  152. package/src/components/avatar/avatar.e2e-test.ts +70 -0
  153. package/src/components/avatar/avatar.stories.ts +25 -0
  154. package/src/components/avatar/avatar.styles.ts +20 -0
  155. package/src/components/avatar/avatar.types.ts +1 -0
  156. package/src/components/avatar/index.ts +12 -0
  157. package/src/components/badge/__screenshots__/mdc-badge.png +0 -0
  158. package/src/components/badge/badge.component.ts +121 -0
  159. package/src/components/badge/badge.constants.ts +13 -0
  160. package/src/components/badge/badge.e2e-test.ts +68 -0
  161. package/src/components/badge/badge.stories.ts +33 -0
  162. package/src/components/badge/badge.styles.ts +26 -0
  163. package/src/components/badge/badge.types.ts +1 -0
  164. package/src/components/badge/index.ts +12 -0
  165. package/src/components/icon/__screenshots__/mdc-icon-default.png +0 -0
  166. package/src/components/icon/__screenshots__/mdc-icon-scale.png +0 -0
  167. package/src/components/icon/icon.component.ts +155 -0
  168. package/src/components/icon/icon.constants.ts +10 -0
  169. package/src/components/icon/icon.e2e-test.ts +101 -0
  170. package/src/components/icon/icon.stories.ts +34 -0
  171. package/src/components/icon/icon.styles.ts +15 -0
  172. package/src/components/icon/icon.utils.ts +13 -0
  173. package/src/components/icon/index.ts +12 -0
  174. package/src/components/iconprovider/__screenshots__/mdc-iconprovider.png +0 -0
  175. package/src/components/iconprovider/iconprovider.component.ts +76 -0
  176. package/src/components/iconprovider/iconprovider.constants.ts +12 -0
  177. package/src/components/iconprovider/iconprovider.context.ts +16 -0
  178. package/src/components/iconprovider/iconprovider.e2e-test.ts +65 -0
  179. package/src/components/iconprovider/iconprovider.stories.ts +27 -0
  180. package/src/components/iconprovider/iconprovider.stories.utils.ts +27 -0
  181. package/src/components/iconprovider/index.ts +12 -0
  182. package/src/components/text/__screenshots__/mdc-text-body-large.png +0 -0
  183. package/src/components/text/__screenshots__/mdc-text-body-regular.png +0 -0
  184. package/src/components/text/__screenshots__/mdc-text-body-small.png +0 -0
  185. package/src/components/text/__screenshots__/mdc-text-heading-1.png +0 -0
  186. package/src/components/text/__screenshots__/mdc-text-heading-2.png +0 -0
  187. package/src/components/text/__screenshots__/mdc-text-heading-3.png +0 -0
  188. package/src/components/text/__screenshots__/mdc-text-heading-4.png +0 -0
  189. package/src/components/text/__screenshots__/mdc-text-heading-5.png +0 -0
  190. package/src/components/text/__screenshots__/mdc-text-heading-6.png +0 -0
  191. package/src/components/text/__screenshots__/mdc-text-heading-7.png +0 -0
  192. package/src/components/text/__screenshots__/mdc-text-image-title.png +0 -0
  193. package/src/components/text/__screenshots__/mdc-text-label.png +0 -0
  194. package/src/components/text/fonts.styles.ts +99 -0
  195. package/src/components/text/index.ts +12 -0
  196. package/src/components/text/text.component.ts +51 -0
  197. package/src/components/text/text.constants.ts +27 -0
  198. package/src/components/text/text.e2e-test.ts +76 -0
  199. package/src/components/text/text.stories.ts +29 -0
  200. package/src/components/text/text.styles.ts +17 -0
  201. package/src/components/text/text.types.ts +13 -0
  202. package/src/components/text/text.utils.ts +51 -0
  203. package/src/components/themeprovider/__screenshots__/mdc-themeprovider-darkWebex.png +0 -0
  204. package/src/components/themeprovider/__screenshots__/mdc-themeprovider-lightWebex.png +0 -0
  205. package/src/components/themeprovider/index.ts +12 -0
  206. package/src/components/themeprovider/themeprovider.component.ts +91 -0
  207. package/src/components/themeprovider/themeprovider.constants.ts +32 -0
  208. package/src/components/themeprovider/themeprovider.context.ts +18 -0
  209. package/src/components/themeprovider/themeprovider.e2e-test.ts +89 -0
  210. package/src/components/themeprovider/themeprovider.stories.styles.css +22 -0
  211. package/src/components/themeprovider/themeprovider.stories.ts +38 -0
  212. package/src/components/themeprovider/themeprovider.stories.utils.ts +23 -0
  213. package/src/components/themeprovider/themeprovider.styles.ts +13 -0
  214. package/src/components/themeprovider/themeprovider.types.ts +7 -0
  215. package/src/components/themeprovider/themeprovider.utils.ts +16 -0
  216. package/src/index.ts +22 -0
  217. package/src/models/component/component.component.ts +46 -0
  218. package/src/models/component/component.types.ts +16 -0
  219. package/src/models/component/index.ts +7 -0
  220. package/src/models/index.ts +11 -0
  221. package/src/models/provider/index.ts +3 -0
  222. package/src/models/provider/provider.component.ts +87 -0
  223. package/src/models/provider/provider.styles.ts +14 -0
  224. package/src/stories/colors.mdx +32 -0
  225. package/src/stories/icons.mdx +13 -0
  226. package/src/stories/typography.mdx +20 -0
  227. package/src/utils/mixins/DisabledMixin.ts +19 -0
  228. package/src/utils/mixins/TabIndexMixin.ts +19 -0
  229. package/src/utils/provider/index.ts +21 -0
  230. package/src/utils/styles/index.ts +13 -0
  231. package/src/utils/tag-name/constants.ts +10 -0
  232. package/src/utils/tag-name/index.ts +15 -0
  233. package/src/utils/types.ts +1 -0
  234. package/tsconfig.json +45 -0
  235. package/tsconfig.module.json +47 -0
@@ -0,0 +1,70 @@
1
+ /* eslint-disable no-restricted-syntax */
2
+ /* eslint-disable no-await-in-loop */
3
+ import { Locator, Page, expect, TestInfo } from '@playwright/test';
4
+ import AxeBuilder from '@axe-core/playwright';
5
+ import CONSTANTS from '../constants';
6
+
7
+ interface Accessibility {
8
+ page: Page;
9
+ testInfo: TestInfo;
10
+ }
11
+
12
+ /**
13
+ * Contains common `accessibility` utils, which are useful when doing accessibility tests
14
+ */
15
+ class Accessibility {
16
+ constructor(page: Page, testInfo: TestInfo) {
17
+ this.page = page;
18
+ this.testInfo = testInfo;
19
+ }
20
+
21
+ /**
22
+ * Attaches the provided scan results as JSON
23
+ * to the test report
24
+ * @param accessibilityScanResults
25
+ */
26
+ async attachA11yResults(accessibilityScanResults: any) {
27
+ await this.testInfo.attach('accessibility-scan-results', {
28
+ body: JSON.stringify(accessibilityScanResults, null, 2),
29
+ contentType: 'application/json',
30
+ });
31
+ }
32
+
33
+ /**
34
+ * Checks for Accessibility violations by scanning the whole
35
+ * page with axe-core, using the specific accessibility WCAG tags to check
36
+ * and disabled rules. The results will be attached as a JSON file
37
+ * to the test report afterwards.
38
+ *
39
+ * This function will fail if there are any accessibility violations.
40
+ */
41
+ async checkForA11yViolations() {
42
+ const accessibilityScanResults = await new AxeBuilder({ page: this.page })
43
+ .withTags(CONSTANTS.ACCESSIBILITY.WCAG_TAGS_TO_CHECK)
44
+ .disableRules(CONSTANTS.ACCESSIBILITY.RULES_TO_DISABLE)
45
+ .analyze();
46
+
47
+ await this.attachA11yResults(accessibilityScanResults);
48
+
49
+ expect(accessibilityScanResults.violations).toEqual([]);
50
+ }
51
+
52
+ /**
53
+ * pressAndCheckFocus utility function - it will press the provided `keyToPress` as often
54
+ * as the provided `elementsToBeFocused` are and checks afterwards, if the provided element of the
55
+ * `elementsToBeFocused` has been focused.
56
+ *
57
+ * If only 1 keyPress needs to be done, just simply provide the `elementsToBeFocused` array with
58
+ * 1 element, which should receive focus.
59
+ * @param keyToPress key which should be pressed
60
+ * @param elementsToBeFocused array of elements, which have to be focused after pressing a key
61
+ */
62
+ async pressAndCheckFocus(keyToPress: string, elementsToBeFocused: Array<Locator>) {
63
+ for (const elementToBeFocused of elementsToBeFocused) {
64
+ await this.page.keyboard.press(keyToPress);
65
+ await expect(elementToBeFocused).toBeFocused();
66
+ }
67
+ }
68
+ }
69
+
70
+ export default Accessibility;
@@ -0,0 +1,35 @@
1
+ import { Page, expect } from '@playwright/test';
2
+ import type { ScreenShotOptions } from '../types';
3
+ import CONSTANTS from '../constants';
4
+
5
+ interface VisualRegression {
6
+ page: Page;
7
+ }
8
+
9
+ /**
10
+ * Contains common `visual-regression` utils, which are useful when doing visual-regression tests
11
+ */
12
+ class VisualRegression {
13
+ constructor(page: Page) {
14
+ this.page = page;
15
+ }
16
+
17
+ /**
18
+ * Takes a screenshot of the whole page, with the passed in options
19
+ *
20
+ * @param name - name of the screenshot, file extension will be appended automatically!
21
+ * @param options - description
22
+ * @param options.element - element to take screenshot from
23
+ */
24
+ async takeScreenshot(name: string, options?: ScreenShotOptions): Promise<void> {
25
+ const elementToTakeScreenShotFrom = options?.element || this.page;
26
+
27
+ expect(await elementToTakeScreenShotFrom.screenshot(options)).toMatchSnapshot({
28
+ name: `${name}.${CONSTANTS.VISUAL_REGRESSION.FILE_EXTENSION}`,
29
+ threshold: CONSTANTS.VISUAL_REGRESSION.THRESHOLD,
30
+ maxDiffPixelRatio: CONSTANTS.VISUAL_REGRESSION.MAX_DIFF_PIXELS_RATIO,
31
+ });
32
+ }
33
+ }
34
+
35
+ export default VisualRegression;
@@ -0,0 +1,21 @@
1
+ import { join } from 'path';
2
+ import { ActionType } from 'plop';
3
+ import { folders, ACTION, TYPE, componentName, componentNamePrefix, componentNameSeparator } from '../constants';
4
+
5
+ const base = `${join(`${folders.templates}`, `${ACTION.ADD}`, `${TYPE.COMPONENT}`)}`;
6
+
7
+ export const AddComponent: ActionType = {
8
+ type: 'addMany',
9
+ base,
10
+ templateFiles: `${join(`${base}`, '**')}`,
11
+ destination: `${join(`${folders.components}`, `{{${componentName}}}`)}`,
12
+ data: {
13
+ componentName,
14
+ prefix: componentNamePrefix,
15
+ separator: componentNameSeparator,
16
+ },
17
+ globOptions: {
18
+ // allow hidden files to be copied as well:
19
+ dot: false,
20
+ },
21
+ };
@@ -0,0 +1,16 @@
1
+ /* eslint-disable max-len */
2
+ import { join } from 'path';
3
+ import { ActionType } from 'plop';
4
+ import { folders, componentName, componentNamePrefix } from '../constants';
5
+
6
+ export const AddToComponentExports: ActionType = {
7
+ type: 'modify',
8
+ path: `${join(`${folders.src}`, 'index.ts')}`,
9
+ pattern: /(};)/g,
10
+ data: {
11
+ componentName,
12
+ prefix: componentNamePrefix,
13
+ },
14
+ template:
15
+ ` {{sentenceCase prefix}}{{sentenceCase ${componentName}}},\n$1`,
16
+ };
@@ -0,0 +1,16 @@
1
+ /* eslint-disable max-len */
2
+ import { join } from 'path';
3
+ import { ActionType } from 'plop';
4
+ import { folders, componentName, componentNamePrefix } from '../constants';
5
+
6
+ export const AddToComponentImports: ActionType = {
7
+ type: 'modify',
8
+ path: `${join(`${folders.src}`, 'index.ts')}`,
9
+ pattern: /(\nexport)/g,
10
+ data: {
11
+ componentName,
12
+ prefix: componentNamePrefix,
13
+ },
14
+ template:
15
+ `import {{sentenceCase prefix}}{{sentenceCase ${componentName}}} from './components/{{${componentName}}}';\n$1`,
16
+ };
@@ -0,0 +1,31 @@
1
+ import { join } from 'path';
2
+ import CONSTANTS from '../../../src/utils/tag-name/constants';
3
+
4
+ export enum PROMPT_TYPE {
5
+ INPUT = 'input',
6
+ }
7
+
8
+ export enum GENERATOR_NAME {
9
+ COMPONENT_GENERATOR = 'component'
10
+ }
11
+
12
+ export enum ACTION {
13
+ ADD = 'add',
14
+ }
15
+
16
+ export enum TYPE {
17
+ COMPONENT = 'component',
18
+ }
19
+
20
+ export const componentName: string = 'componentName';
21
+ export const componentNamePrefix: string = CONSTANTS.NAMESPACE.PREFIX;
22
+ export const componentNameSeparator: string = CONSTANTS.NAMESPACE.SEPARATOR;
23
+
24
+ export const root: string = process.cwd();
25
+ export const plop: string = `${join(root, 'config', 'plop')}`;
26
+
27
+ export const folders = {
28
+ src: `${join(root, 'src')}`,
29
+ components: `${join(root, 'src', 'components')}`,
30
+ templates: `${join(plop, 'templates')}`,
31
+ };
@@ -0,0 +1,4 @@
1
+ // TODO: look into how to use this from momentum-design inside of here without relative import
2
+ const { plop } = require('../../../../../config/esbuild/esbuild.config.js');
3
+
4
+ plop();
@@ -0,0 +1,25 @@
1
+ /* eslint-disable quotes */
2
+ import { PlopGeneratorConfig } from 'plop';
3
+
4
+ import { GENERATOR_NAME, componentName, PROMPT_TYPE } from '../../constants';
5
+ import { AddComponent } from '../../actions/AddComponent';
6
+ import { prompt } from '../../prompts';
7
+ import { AddToComponentImports } from '../../actions/AddToComponentImports';
8
+ import { AddToComponentExports } from '../../actions/AddToComponentExports';
9
+
10
+ const componentNameMessage = `Choose the name of the component.
11
+ Requirements
12
+ - lowercase
13
+ - without prefix e.g. "button"
14
+ - no additional "hyphens", like "theme-provider"
15
+ `;
16
+ const generator: Partial<PlopGeneratorConfig> = {
17
+ description: 'Scaffold a new package',
18
+ prompts: [prompt(`${componentName}`, componentNameMessage, PROMPT_TYPE.INPUT)],
19
+ actions: [AddComponent, AddToComponentImports, AddToComponentExports],
20
+ };
21
+
22
+ export const ComponentGenerator = {
23
+ name: GENERATOR_NAME.COMPONENT_GENERATOR,
24
+ generator,
25
+ };
@@ -0,0 +1,6 @@
1
+ import { NodePlopAPI } from 'plop';
2
+ import { ComponentGenerator } from './generators/component';
3
+
4
+ export default (plop: NodePlopAPI) => {
5
+ plop.setGenerator(ComponentGenerator.name, ComponentGenerator.generator);
6
+ };
@@ -0,0 +1,8 @@
1
+ import { PromptQuestion } from 'node-plop';
2
+ import { PROMPT_TYPE } from '../constants';
3
+
4
+ export const prompt = (name: string, message: string, type: PROMPT_TYPE = PROMPT_TYPE.INPUT): PromptQuestion => ({
5
+ type,
6
+ name,
7
+ message,
8
+ });
@@ -0,0 +1,12 @@
1
+ import {{sentenceCase componentName}} from './{{componentName}}.component';
2
+ import { TAG_NAME } from './{{componentName}}.constants';
3
+
4
+ {{sentenceCase componentName}}.register(TAG_NAME);
5
+
6
+ declare global {
7
+ interface HTMLElementTagNameMap {
8
+ ['{{prefix}}{{separator}}{{componentName}}']: {{sentenceCase componentName}}
9
+ }
10
+ }
11
+
12
+ export default {{sentenceCase componentName}};
@@ -0,0 +1,22 @@
1
+ import { html } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
+ import styles from './{{componentName}}.styles';
4
+ import { Component } from '../../models';
5
+
6
+ /**
7
+ * @slot - This is a default/unnamed slot
8
+ *
9
+ * @summary This is MyElement
10
+ *
11
+ * @tag {{prefix}}-{{componentName}}
12
+ * @tagname {{prefix}}-{{componentName}}
13
+ */
14
+ class {{sentenceCase prefix}}{{sentenceCase componentName}} extends Component {
15
+ public override render() {
16
+ return html`<p>This is a dummy component!</p><slot></slot>`;
17
+ }
18
+
19
+ public static override styles = styles;
20
+ }
21
+
22
+ export default {{sentenceCase componentName}};
@@ -0,0 +1,5 @@
1
+ import utils from '../../utils/tag-name';
2
+
3
+ const TAG_NAME = utils.constructTagName('{{componentName}}');
4
+
5
+ export { TAG_NAME };
@@ -0,0 +1,67 @@
1
+ import { test } from '../../../config/playwright/setup';
2
+ import steps from '../../../config/playwright/setup/steps/accessibility';
3
+
4
+ test.beforeEach(async ({ componentsPage }) => {
5
+ await componentsPage.mount({
6
+ html: `
7
+ <{{prefix}}{{separator}}{{componentName}} />
8
+ `,
9
+ });
10
+ });
11
+
12
+ test('{{prefix}}{{separator}}{{componentName}}', async ({ componentsPage }) => {
13
+ const {{componentName}} = componentsPage.page.locator('{{prefix}}-{{componentName}}');
14
+
15
+ // initial check for the {{componentName}} be visible on the screen:
16
+ await {{componentName}}.waitFor();
17
+
18
+ /**
19
+ * ACCESSIBILITY
20
+ */
21
+ await test.step('accessibility', async () => {
22
+ await steps.automaticA11yCheckStep(componentsPage);
23
+ });
24
+
25
+ /**
26
+ * VISUAL REGRESSION
27
+ */
28
+ await test.step('visual-regression', async () => {
29
+ await test.step('matches screenshot of element', async () => {
30
+ await componentsPage.visualRegression.takeScreenshot('{{prefix}}{{separator}}{{componentName}}', { element: {{componentName}} });
31
+ });
32
+ });
33
+
34
+ /**
35
+ * ATTRIBUTES
36
+ */
37
+ await test.step('attributes', async () => {
38
+ await test.step('attribute X should be present on component by default', async () => {
39
+ // TODO: add test here
40
+ });
41
+ });
42
+
43
+ /**
44
+ * INTERACTIONS
45
+ */
46
+ await test.step('interactions', async () => {
47
+ await test.step('mouse/pointer', async () => {
48
+ await test.step('component should fire callback x when clicking on it', async () => {
49
+ // TODO: add test here
50
+ });
51
+ });
52
+
53
+ await test.step('focus', async () => {
54
+ await test.step('component should be focusable with tab', async () => {
55
+ // TODO: add test here
56
+ });
57
+
58
+ // add additional tests here, like tabbing through several parts of the component
59
+ });
60
+
61
+ await test.step('keyboard', async () => {
62
+ await test.step('component should fire callback x when pressing y', async () => {
63
+ // TODO: add test here
64
+ });
65
+ });
66
+ });
67
+ });
@@ -0,0 +1,13 @@
1
+ import { html } from 'lit';
2
+
3
+ type Args = {}
4
+
5
+ const base = (args: Args) => html`
6
+ <{{prefix}}{{separator}}{{componentName}}></{{prefix}}{{separator}}{{componentName}}>
7
+ `;
8
+
9
+ const fixtures = {
10
+ base,
11
+ };
12
+
13
+ export default fixtures;
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj, Args } from '@storybook/web-components';
2
+ import '.';
3
+ import fixtures from './{{componentName}}.fixtures';
4
+
5
+ const render = (args: Args) => fixtures.base(args);
6
+
7
+ const meta: Meta = {
8
+ tags: ['autodocs'],
9
+ component: '{{prefix}}{{separator}}{{componentName}}',
10
+ render,
11
+ argTypes: {},
12
+ };
13
+
14
+ export default meta;
15
+
16
+ export const Primary: StoryObj = {
17
+ args: {},
18
+ };
@@ -0,0 +1,8 @@
1
+ import { css } from 'lit';
2
+
3
+ const styles = css`
4
+ :host {
5
+ }
6
+ `;
7
+
8
+ export default styles;
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "./dist",
4
+ "module": "CommonJS",
5
+ "esModuleInterop": true,
6
+ "moduleResolution": "node"
7
+ },
8
+ "exclude": [
9
+ "./templates"
10
+ ]
11
+ }
@@ -0,0 +1,41 @@
1
+ import { create } from '@storybook/theming/create';
2
+
3
+ export default create({
4
+ base: 'dark',
5
+
6
+ // Typography for Manager
7
+ // (can't use Inter here without a lot of workarounds):
8
+ fontBase: 'Helvetica Neue, sans-serif',
9
+ fontCode: 'monospace',
10
+
11
+ brandTitle: 'Momentum Design',
12
+ brandUrl: 'https://momentum.design',
13
+ brandImage: '/momentum-logo.png',
14
+ brandTarget: '_self',
15
+
16
+ colorPrimary: '#64b4fa',
17
+ colorSecondary: '#64b4fa',
18
+
19
+ // UI
20
+ appBg: '#1a1a1a',
21
+ appContentBg: '#262626',
22
+ appBorderColor: '#ffffff4d',
23
+
24
+ // Text colors
25
+ textColor: '#FFFFF2',
26
+ textInverseColor: '#000002',
27
+
28
+ // Toolbar default and active colors
29
+ barTextColor: '#FFFFF2',
30
+ barSelectedColor: '#64b4fa',
31
+ barBg: '#262626',
32
+
33
+ // Form colors
34
+ inputBg: '#FFFFFF',
35
+ inputBorder: '#ffffffb3',
36
+ inputTextColor: '#000002',
37
+
38
+ // Buttons:
39
+ buttonBg: '#FFFFFF',
40
+ buttonBorder: '#ffffffb3',
41
+ });
@@ -0,0 +1,21 @@
1
+ const config = {
2
+ stories: ['../../src/**/*.stories.@(js|jsx|ts|tsx)', '../../src/stories/**/*.mdx'],
3
+ addons: [
4
+ '@storybook/addon-controls',
5
+ '@storybook/addon-links',
6
+ '@storybook/addon-essentials',
7
+ '@storybook/addon-a11y',
8
+ ],
9
+ framework: {
10
+ name: '@storybook/web-components-vite',
11
+ options: {},
12
+ },
13
+ core: {
14
+ disableTelemetry: true, // 👈 Disables telemetry
15
+ },
16
+ docs: {
17
+ autodocs: 'tag',
18
+ },
19
+ staticDirs: ['./public'],
20
+ };
21
+ export default config;
@@ -0,0 +1,17 @@
1
+ import { addons } from '@storybook/manager-api';
2
+ import momentum from './MomentumStorybookTheme';
3
+
4
+ addons.setConfig({
5
+ bottomPanelHeight: '500',
6
+ panelPosition: 'bottom',
7
+ sidebar: {
8
+ showRoots: true,
9
+ },
10
+ toolbar: {
11
+ zoom: { hidden: false },
12
+ eject: { hidden: false },
13
+ copy: { hidden: false },
14
+ fullscreen: { hidden: false },
15
+ },
16
+ theme: momentum,
17
+ });
@@ -0,0 +1,63 @@
1
+ import '../../src/components/themeprovider';
2
+ import '@momentum-design/tokens/dist/css/core/complete.css';
3
+ import '@momentum-design/tokens/dist/css/theme/webex/dark-stable.css';
4
+ import '@momentum-design/tokens/dist/css/theme/webex/light-stable.css';
5
+ import '@momentum-design/fonts/dist/css/fonts.css';
6
+
7
+ import { setCustomElementsManifest } from '@storybook/web-components';
8
+ import customElements from '../../data/custom-elements.json';
9
+ import { themes } from './themes';
10
+ import { withThemeProvider } from './provider/themeProvider';
11
+ import { withIconProvider } from './provider/iconProvider';
12
+
13
+ setCustomElementsManifest(customElements);
14
+
15
+ const preview = {
16
+ parameters: {
17
+ a11y: {
18
+ options: {
19
+ runOnly: {
20
+ type: 'tag',
21
+ values: ['best-practice', 'wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa'],
22
+ },
23
+ },
24
+ },
25
+ backgrounds: {
26
+ disable: true,
27
+ grid: {
28
+ disable: true,
29
+ },
30
+ },
31
+ actions: { argTypesRegex: '^on[A-Z].*' },
32
+ controls: {
33
+ controls: { expanded: true },
34
+ matchers: {
35
+ color: /(background|color)$/i,
36
+ date: /Date$/,
37
+ },
38
+ },
39
+ options: {
40
+ storySort: {
41
+ order: ['System', 'Components'],
42
+ },
43
+ },
44
+ },
45
+ decorators: [withThemeProvider, withIconProvider],
46
+ globalTypes: {
47
+ theme: {
48
+ description: 'Global theme for components',
49
+ defaultValue: themes[0].displayName,
50
+ toolbar: {
51
+ // The label to show for this toolbar item
52
+ title: 'Theme',
53
+ icon: 'globe',
54
+ // Array of plain string values or MenuItem shape (see below)
55
+ items: themes.map((theme) => theme.displayName),
56
+ // Change title based on selected value
57
+ dynamicTitle: true,
58
+ },
59
+ },
60
+ },
61
+ };
62
+
63
+ export default preview;
@@ -0,0 +1,8 @@
1
+ import { html } from 'lit';
2
+
3
+ export const withIconProvider = (story) =>
4
+ html`<mdc-iconprovider
5
+ url="/icons/svg"
6
+ >
7
+ ${story()}
8
+ </mdc-iconprovider>`;
@@ -0,0 +1,31 @@
1
+ import { html } from 'lit';
2
+ import { themes } from '../themes';
3
+ import '../themes/themes.css';
4
+
5
+ const clearStyles = (element) => {
6
+ // eslint-disable-next-line no-restricted-syntax
7
+ for (const theme of themes) {
8
+ element.classList.remove(theme.className);
9
+ }
10
+ };
11
+
12
+ const applyStyle = (element, className) => {
13
+ element.classList.add(className);
14
+ };
15
+
16
+ export const withThemeProvider = (story, context) => {
17
+ const currentTheme = context.globals.theme;
18
+ const themeObject = themes.find((theme) => theme.displayName === currentTheme);
19
+
20
+ const body = document.querySelector('body.sb-show-main');
21
+ clearStyles(body);
22
+ applyStyle(body, themeObject.className);
23
+
24
+ return html`<mdc-themeprovider
25
+ id="theme-provider"
26
+ theme="${themeObject.name}"
27
+ themes="mds-theme-stable-darkWebex mds-theme-stable-lightWebex"
28
+ >
29
+ ${story()}
30
+ </mdc-themeprovider>`;
31
+ };
@@ -0,0 +1,14 @@
1
+ export const themes = [
2
+ {
3
+ name: 'mds-theme-stable-darkWebex',
4
+ displayName: 'darkWebex',
5
+ backgroundColor: '#000000',
6
+ className: 'dark',
7
+ },
8
+ {
9
+ name: 'mds-theme-stable-lightWebex',
10
+ displayName: 'lightWebex',
11
+ backgroundColor: '#ffffff',
12
+ className: 'light',
13
+ },
14
+ ];
@@ -0,0 +1,15 @@
1
+ .dark {
2
+ background-color: #000000;
3
+ height: 100vh;
4
+ background-image: url('/background-graphic.png');
5
+ background-repeat: no-repeat;
6
+ background-position: top right;
7
+ }
8
+
9
+ .light {
10
+ background-color: #ffffff;
11
+ height: 100vh;
12
+ background-image: url('/background-graphic.png');
13
+ background-repeat: no-repeat;
14
+ background-position: top right;
15
+ }