@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.
- package/.eslintrc.js +16 -0
- package/CONTRIBUTING.md +5 -0
- package/README.md +39 -0
- package/SCRIPTS.md +15 -0
- package/TESTING.md +38 -0
- package/config/api-extractor.json +33 -0
- package/config/custom-elements-manifest.config.js +28 -0
- package/config/esbuild/configs/browser.js +21 -0
- package/config/esbuild/configs/e2e.js +10 -0
- package/config/esbuild/esbuild-e2e.config.js +22 -0
- package/config/esbuild/esbuild.config.js +9 -0
- package/config/playwright/playwright.config.ts +107 -0
- package/config/playwright/public/index.css +43 -0
- package/config/playwright/public/index.html +26 -0
- package/config/playwright/setup/Components.page.ts +163 -0
- package/config/playwright/setup/constants.ts +27 -0
- package/config/playwright/setup/index.ts +42 -0
- package/config/playwright/setup/steps/accessibility.ts +9 -0
- package/config/playwright/setup/types.ts +5 -0
- package/config/playwright/setup/utils/accessibility.ts +70 -0
- package/config/playwright/setup/utils/visual-regression.ts +35 -0
- package/config/plop/actions/AddComponent.ts +21 -0
- package/config/plop/actions/AddToComponentExports.ts +16 -0
- package/config/plop/actions/AddToComponentImports.ts +16 -0
- package/config/plop/constants/index.ts +31 -0
- package/config/plop/esbuild.config.plop.js +4 -0
- package/config/plop/generators/component/index.ts +25 -0
- package/config/plop/plopfile.ts +6 -0
- package/config/plop/prompts/index.ts +8 -0
- package/config/plop/templates/add/component/index.ts.hbs +12 -0
- package/config/plop/templates/add/component/{{componentName}}.component.ts.hbs +22 -0
- package/config/plop/templates/add/component/{{componentName}}.constants.ts.hbs +5 -0
- package/config/plop/templates/add/component/{{componentName}}.e2e-test.ts.hbs +67 -0
- package/config/plop/templates/add/component/{{componentName}}.fixtures.ts.hbs +13 -0
- package/config/plop/templates/add/component/{{componentName}}.stories.ts.hbs +18 -0
- package/config/plop/templates/add/component/{{componentName}}.styles.ts.hbs +8 -0
- package/config/plop/tsconfig.plop.json +11 -0
- package/config/storybook/MomentumStorybookTheme.js +41 -0
- package/config/storybook/main.js +21 -0
- package/config/storybook/manager.js +17 -0
- package/config/storybook/preview.js +63 -0
- package/config/storybook/provider/iconProvider.js +8 -0
- package/config/storybook/provider/themeProvider.js +31 -0
- package/config/storybook/public/background-graphic.png +0 -0
- package/config/storybook/public/fonts/Inter.var.woff2 +0 -0
- package/config/storybook/public/momentum-logo.png +0 -0
- package/config/storybook/themes/index.js +14 -0
- package/config/storybook/themes/themes.css +15 -0
- package/data/custom-elements.json +677 -0
- package/dist/browser/index.js +366 -0
- package/dist/browser/index.js.map +7 -0
- package/dist/components/avatar/avatar.component.d.ts +28 -0
- package/dist/components/avatar/avatar.component.js +79 -0
- package/dist/components/avatar/avatar.constants.d.ts +7 -0
- package/dist/components/avatar/avatar.constants.js +14 -0
- package/dist/components/avatar/avatar.styles.d.ts +2 -0
- package/dist/components/avatar/avatar.styles.js +20 -0
- package/dist/components/avatar/avatar.types.d.ts +1 -0
- package/dist/components/avatar/avatar.types.js +2 -0
- package/dist/components/avatar/index.d.ts +7 -0
- package/dist/components/avatar/index.js +7 -0
- package/dist/components/badge/badge.component.d.ts +51 -0
- package/dist/components/badge/badge.component.js +114 -0
- package/dist/components/badge/badge.constants.d.ts +8 -0
- package/dist/components/badge/badge.constants.js +15 -0
- package/dist/components/badge/badge.styles.d.ts +2 -0
- package/dist/components/badge/badge.styles.js +26 -0
- package/dist/components/badge/badge.types.d.ts +1 -0
- package/dist/components/badge/badge.types.js +2 -0
- package/dist/components/badge/index.d.ts +7 -0
- package/dist/components/badge/index.js +7 -0
- package/dist/components/icon/icon.component.d.ts +63 -0
- package/dist/components/icon/icon.component.js +158 -0
- package/dist/components/icon/icon.constants.d.ts +6 -0
- package/dist/components/icon/icon.constants.js +12 -0
- package/dist/components/icon/icon.styles.d.ts +2 -0
- package/dist/components/icon/icon.styles.js +15 -0
- package/dist/components/icon/icon.utils.d.ts +2 -0
- package/dist/components/icon/icon.utils.js +13 -0
- package/dist/components/icon/index.d.ts +7 -0
- package/dist/components/icon/index.js +7 -0
- package/dist/components/iconprovider/iconprovider.component.d.ts +34 -0
- package/dist/components/iconprovider/iconprovider.component.js +71 -0
- package/dist/components/iconprovider/iconprovider.constants.d.ts +7 -0
- package/dist/components/iconprovider/iconprovider.constants.js +14 -0
- package/dist/components/iconprovider/iconprovider.context.d.ts +9 -0
- package/dist/components/iconprovider/iconprovider.context.js +9 -0
- package/dist/components/iconprovider/index.d.ts +7 -0
- package/dist/components/iconprovider/index.js +7 -0
- package/dist/components/text/fonts.styles.d.ts +1 -0
- package/dist/components/text/fonts.styles.js +100 -0
- package/dist/components/text/index.d.ts +7 -0
- package/dist/components/text/index.js +7 -0
- package/dist/components/text/text.component.d.ts +29 -0
- package/dist/components/text/text.component.js +41 -0
- package/dist/components/text/text.constants.d.ts +9 -0
- package/dist/components/text/text.constants.js +28 -0
- package/dist/components/text/text.styles.d.ts +2 -0
- package/dist/components/text/text.styles.js +17 -0
- package/dist/components/text/text.types.d.ts +1 -0
- package/dist/components/text/text.types.js +2 -0
- package/dist/components/text/text.utils.d.ts +20 -0
- package/dist/components/text/text.utils.js +50 -0
- package/dist/components/themeprovider/index.d.ts +7 -0
- package/dist/components/themeprovider/index.js +7 -0
- package/dist/components/themeprovider/themeprovider.component.d.ts +48 -0
- package/dist/components/themeprovider/themeprovider.component.js +86 -0
- package/dist/components/themeprovider/themeprovider.constants.d.ts +10 -0
- package/dist/components/themeprovider/themeprovider.constants.js +31 -0
- package/dist/components/themeprovider/themeprovider.context.d.ts +9 -0
- package/dist/components/themeprovider/themeprovider.context.js +13 -0
- package/dist/components/themeprovider/themeprovider.styles.d.ts +2 -0
- package/dist/components/themeprovider/themeprovider.styles.js +13 -0
- package/dist/components/themeprovider/themeprovider.types.d.ts +5 -0
- package/dist/components/themeprovider/themeprovider.types.js +2 -0
- package/dist/components/themeprovider/themeprovider.utils.d.ts +9 -0
- package/dist/components/themeprovider/themeprovider.utils.js +10 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +19 -0
- package/dist/models/component/component.component.d.ts +38 -0
- package/dist/models/component/component.component.js +45 -0
- package/dist/models/component/component.types.d.ts +15 -0
- package/dist/models/component/component.types.js +2 -0
- package/dist/models/component/index.d.ts +3 -0
- package/dist/models/component/index.js +5 -0
- package/dist/models/index.d.ts +4 -0
- package/dist/models/index.js +8 -0
- package/dist/models/provider/index.d.ts +2 -0
- package/dist/models/provider/index.js +5 -0
- package/dist/models/provider/provider.component.d.ts +70 -0
- package/dist/models/provider/provider.component.js +56 -0
- package/dist/models/provider/provider.styles.d.ts +2 -0
- package/dist/models/provider/provider.styles.js +14 -0
- package/dist/utils/provider/index.d.ts +13 -0
- package/dist/utils/provider/index.js +14 -0
- package/dist/utils/styles/index.d.ts +2 -0
- package/dist/utils/styles/index.js +14 -0
- package/dist/utils/tag-name/constants.d.ts +7 -0
- package/dist/utils/tag-name/constants.js +10 -0
- package/dist/utils/tag-name/index.d.ts +4 -0
- package/dist/utils/tag-name/index.js +10 -0
- package/dist/utils/types.d.ts +1 -0
- package/dist/utils/types.js +2 -0
- package/jest.config.js +3 -0
- package/package.json +78 -0
- package/scripts/copyFonts.js +31 -0
- package/scripts/copyIcons.js +31 -0
- package/scripts/copyTokens.js +24 -0
- package/src/components/avatar/__screenshots__/mdc-avatar.png +0 -0
- package/src/components/avatar/avatar.component.ts +74 -0
- package/src/components/avatar/avatar.constants.ts +12 -0
- package/src/components/avatar/avatar.e2e-test.ts +70 -0
- package/src/components/avatar/avatar.stories.ts +25 -0
- package/src/components/avatar/avatar.styles.ts +20 -0
- package/src/components/avatar/avatar.types.ts +1 -0
- package/src/components/avatar/index.ts +12 -0
- package/src/components/badge/__screenshots__/mdc-badge.png +0 -0
- package/src/components/badge/badge.component.ts +121 -0
- package/src/components/badge/badge.constants.ts +13 -0
- package/src/components/badge/badge.e2e-test.ts +68 -0
- package/src/components/badge/badge.stories.ts +33 -0
- package/src/components/badge/badge.styles.ts +26 -0
- package/src/components/badge/badge.types.ts +1 -0
- package/src/components/badge/index.ts +12 -0
- package/src/components/icon/__screenshots__/mdc-icon-default.png +0 -0
- package/src/components/icon/__screenshots__/mdc-icon-scale.png +0 -0
- package/src/components/icon/icon.component.ts +155 -0
- package/src/components/icon/icon.constants.ts +10 -0
- package/src/components/icon/icon.e2e-test.ts +101 -0
- package/src/components/icon/icon.stories.ts +34 -0
- package/src/components/icon/icon.styles.ts +15 -0
- package/src/components/icon/icon.utils.ts +13 -0
- package/src/components/icon/index.ts +12 -0
- package/src/components/iconprovider/__screenshots__/mdc-iconprovider.png +0 -0
- package/src/components/iconprovider/iconprovider.component.ts +76 -0
- package/src/components/iconprovider/iconprovider.constants.ts +12 -0
- package/src/components/iconprovider/iconprovider.context.ts +16 -0
- package/src/components/iconprovider/iconprovider.e2e-test.ts +65 -0
- package/src/components/iconprovider/iconprovider.stories.ts +27 -0
- package/src/components/iconprovider/iconprovider.stories.utils.ts +27 -0
- package/src/components/iconprovider/index.ts +12 -0
- package/src/components/text/__screenshots__/mdc-text-body-large.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-body-regular.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-body-small.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-heading-1.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-heading-2.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-heading-3.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-heading-4.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-heading-5.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-heading-6.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-heading-7.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-image-title.png +0 -0
- package/src/components/text/__screenshots__/mdc-text-label.png +0 -0
- package/src/components/text/fonts.styles.ts +99 -0
- package/src/components/text/index.ts +12 -0
- package/src/components/text/text.component.ts +51 -0
- package/src/components/text/text.constants.ts +27 -0
- package/src/components/text/text.e2e-test.ts +76 -0
- package/src/components/text/text.stories.ts +29 -0
- package/src/components/text/text.styles.ts +17 -0
- package/src/components/text/text.types.ts +13 -0
- package/src/components/text/text.utils.ts +51 -0
- package/src/components/themeprovider/__screenshots__/mdc-themeprovider-darkWebex.png +0 -0
- package/src/components/themeprovider/__screenshots__/mdc-themeprovider-lightWebex.png +0 -0
- package/src/components/themeprovider/index.ts +12 -0
- package/src/components/themeprovider/themeprovider.component.ts +91 -0
- package/src/components/themeprovider/themeprovider.constants.ts +32 -0
- package/src/components/themeprovider/themeprovider.context.ts +18 -0
- package/src/components/themeprovider/themeprovider.e2e-test.ts +89 -0
- package/src/components/themeprovider/themeprovider.stories.styles.css +22 -0
- package/src/components/themeprovider/themeprovider.stories.ts +38 -0
- package/src/components/themeprovider/themeprovider.stories.utils.ts +23 -0
- package/src/components/themeprovider/themeprovider.styles.ts +13 -0
- package/src/components/themeprovider/themeprovider.types.ts +7 -0
- package/src/components/themeprovider/themeprovider.utils.ts +16 -0
- package/src/index.ts +22 -0
- package/src/models/component/component.component.ts +46 -0
- package/src/models/component/component.types.ts +16 -0
- package/src/models/component/index.ts +7 -0
- package/src/models/index.ts +11 -0
- package/src/models/provider/index.ts +3 -0
- package/src/models/provider/provider.component.ts +87 -0
- package/src/models/provider/provider.styles.ts +14 -0
- package/src/stories/colors.mdx +32 -0
- package/src/stories/icons.mdx +13 -0
- package/src/stories/typography.mdx +20 -0
- package/src/utils/mixins/DisabledMixin.ts +19 -0
- package/src/utils/mixins/TabIndexMixin.ts +19 -0
- package/src/utils/provider/index.ts +21 -0
- package/src/utils/styles/index.ts +13 -0
- package/src/utils/tag-name/constants.ts +10 -0
- package/src/utils/tag-name/index.ts +15 -0
- package/src/utils/types.ts +1 -0
- package/tsconfig.json +45 -0
- package/tsconfig.module.json +47 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
// todo: change definition to tokens once available
|
|
4
|
+
|
|
5
|
+
export const fontsStyles = css`
|
|
6
|
+
:host([type="heading-1"]) {
|
|
7
|
+
font-size: 7.5rem;
|
|
8
|
+
font-style: normal;
|
|
9
|
+
font-weight: 700;
|
|
10
|
+
line-height: 125%; /* 9.375rem */
|
|
11
|
+
text-transform: capitalize;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:host([type="heading-2"]) {
|
|
15
|
+
font-size: 6rem;
|
|
16
|
+
font-style: normal;
|
|
17
|
+
font-weight: 700;
|
|
18
|
+
line-height: 125%; /* 7.5rem */
|
|
19
|
+
text-transform: capitalize;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
:host([type="heading-3"]) {
|
|
23
|
+
font-size: 3rem;
|
|
24
|
+
font-style: normal;
|
|
25
|
+
font-weight: 700;
|
|
26
|
+
line-height: 125%; /* 3.75rem */
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
:host([type="heading-4"]) {
|
|
30
|
+
font-size: 2.5rem;
|
|
31
|
+
font-style: normal;
|
|
32
|
+
font-weight: 700;
|
|
33
|
+
line-height: 125%; /* 3.125rem */
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:host([type="heading-5"]) {
|
|
37
|
+
font-size: 2rem;
|
|
38
|
+
font-style: normal;
|
|
39
|
+
font-weight: 700;
|
|
40
|
+
line-height: 125%; /* 2.5rem */
|
|
41
|
+
letter-spacing: 0.5rem;
|
|
42
|
+
text-transform: uppercase;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:host([type="heading-6"]) {
|
|
46
|
+
font-size: 1.75rem;
|
|
47
|
+
font-style: normal;
|
|
48
|
+
font-weight: 700;
|
|
49
|
+
line-height: 3rem; /* 171.429% */
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
:host([type="heading-7"]) {
|
|
53
|
+
font-size: 1.5rem;
|
|
54
|
+
font-style: normal;
|
|
55
|
+
font-weight: 700;
|
|
56
|
+
line-height: 140%; /* 2.1rem */
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:host([type="body-large"]) {
|
|
60
|
+
font-size: 2rem;
|
|
61
|
+
font-style: normal;
|
|
62
|
+
font-weight: 400;
|
|
63
|
+
line-height: 150%; /* 3rem */
|
|
64
|
+
margin-block-end: 1.875em; /* paragraph spacing, 30px */
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
:host([type="body-regular"]) {
|
|
68
|
+
font-size: 1.5rem;
|
|
69
|
+
font-style: normal;
|
|
70
|
+
font-weight: 400;
|
|
71
|
+
line-height: 150%; /* 2.25rem */
|
|
72
|
+
margin-block-end: 1.5em; /* paragraph spacing, 24px */
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
:host([type="body-small"]) {
|
|
76
|
+
font-size: 1.25rem;
|
|
77
|
+
font-style: normal;
|
|
78
|
+
font-weight: 400;
|
|
79
|
+
line-height: 150%; /* 1.875rem */
|
|
80
|
+
margin-block-end: 0.125rem; /* paragraph spacing, 2px */
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
:host([type="image-title"]) {
|
|
84
|
+
font-size: 1rem;
|
|
85
|
+
font-style: normal;
|
|
86
|
+
font-weight: 700;
|
|
87
|
+
line-height: 150%; /* 1.5rem */
|
|
88
|
+
letter-spacing: 0.04rem;
|
|
89
|
+
text-transform: uppercase;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
:host([type="label"]) {
|
|
93
|
+
font-size: 1rem;
|
|
94
|
+
font-style: normal;
|
|
95
|
+
font-weight: 700;
|
|
96
|
+
line-height: 150%; /* 1.5rem */
|
|
97
|
+
letter-spacing: 0.02rem;
|
|
98
|
+
}
|
|
99
|
+
`;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { property } from 'lit/decorators.js';
|
|
3
|
+
import styles from './text.styles';
|
|
4
|
+
import { Component } from '../../models';
|
|
5
|
+
import type { FontType } from './text.types';
|
|
6
|
+
import { getRole, getAriaLevel } from './text.utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Text component, which helps creating a text element aligning with
|
|
10
|
+
* styling.
|
|
11
|
+
*
|
|
12
|
+
* The `type` attribute allows changing the type of text, like `heading-1`, etc.
|
|
13
|
+
*
|
|
14
|
+
* For accessibility the `role` and `aria-level` on the component are going to be set
|
|
15
|
+
* automatically based on the type e.g. heading-1 will lead to `role="heading"` and `aria-level=1`.
|
|
16
|
+
*
|
|
17
|
+
* @tag mdc-text
|
|
18
|
+
* @tagname mdc-text
|
|
19
|
+
*/
|
|
20
|
+
class Text extends Component {
|
|
21
|
+
/**
|
|
22
|
+
* Text Type - defines how the text should be rendered
|
|
23
|
+
*
|
|
24
|
+
* Possible values: `heading-1` | `heading-2` | `heading-3` | `heading-4`
|
|
25
|
+
| `heading-5` | `heading-6` | `heading-7` | `body-large` | `body-regular`
|
|
26
|
+
| `body-small` | `image-title` | `label`;
|
|
27
|
+
*/
|
|
28
|
+
@property({ attribute: 'type', reflect: true, type: String })
|
|
29
|
+
public type?: FontType;
|
|
30
|
+
|
|
31
|
+
protected handleTypeChanged(): void {
|
|
32
|
+
this.role = getRole(this.type);
|
|
33
|
+
this.ariaLevel = getAriaLevel(this.type);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
protected override updated(changedProperties: Map<string, any>): void {
|
|
37
|
+
super.updated(changedProperties);
|
|
38
|
+
|
|
39
|
+
if (changedProperties.has('type')) {
|
|
40
|
+
this.handleTypeChanged();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public override render() {
|
|
45
|
+
return html`<slot></slot>`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public static override styles = styles;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default Text;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import utils from '../../utils/tag-name';
|
|
2
|
+
import type { FontType } from './text.types';
|
|
3
|
+
|
|
4
|
+
const TAG_NAME = utils.constructTagName('text');
|
|
5
|
+
|
|
6
|
+
const DEFAULTS = {
|
|
7
|
+
TYPE: 'body-regular' as const,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const VALUES: {TYPE: Array<FontType>} = {
|
|
11
|
+
TYPE: [
|
|
12
|
+
'heading-1',
|
|
13
|
+
'heading-2',
|
|
14
|
+
'heading-3',
|
|
15
|
+
'heading-4',
|
|
16
|
+
'heading-5',
|
|
17
|
+
'heading-6',
|
|
18
|
+
'heading-7',
|
|
19
|
+
'body-large',
|
|
20
|
+
'body-regular',
|
|
21
|
+
'body-small',
|
|
22
|
+
'image-title',
|
|
23
|
+
'label',
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { TAG_NAME, DEFAULTS, VALUES };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-syntax */
|
|
2
|
+
import { expect } from '@playwright/test';
|
|
3
|
+
import { ComponentsPage, test } from '../../../config/playwright/setup';
|
|
4
|
+
import steps from '../../../config/playwright/setup/steps/accessibility';
|
|
5
|
+
import { VALUES } from './text.constants';
|
|
6
|
+
import { FontType } from './text.types';
|
|
7
|
+
import { getAriaLevel, isHeading } from './text.utils';
|
|
8
|
+
|
|
9
|
+
type SetupOptions = {
|
|
10
|
+
componentsPage: ComponentsPage;
|
|
11
|
+
type: FontType;
|
|
12
|
+
children: any;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const setup = async (args: SetupOptions) => {
|
|
16
|
+
const { componentsPage, ...restArgs } = args;
|
|
17
|
+
await componentsPage.mount({
|
|
18
|
+
html: `
|
|
19
|
+
<mdc-text type="${restArgs.type}">${restArgs.children}</mdc-text>
|
|
20
|
+
`,
|
|
21
|
+
clearDocument: true,
|
|
22
|
+
});
|
|
23
|
+
const text = componentsPage.page.locator('mdc-text');
|
|
24
|
+
await text.waitFor();
|
|
25
|
+
return text;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const typesToTest: Array<FontType> = VALUES.TYPE;
|
|
29
|
+
|
|
30
|
+
test.describe('mdc-text', () => {
|
|
31
|
+
test.use({
|
|
32
|
+
viewport: {
|
|
33
|
+
width: 3000,
|
|
34
|
+
height: 500,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
for (const textType of typesToTest) {
|
|
38
|
+
test(textType, async ({ componentsPage }) => {
|
|
39
|
+
const textContent = 'abcdefghijklmnopqrstuvwxyz1234567890';
|
|
40
|
+
const text = await setup({ componentsPage, type: textType, children: textContent });
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* ACCESSIBILITY
|
|
44
|
+
*/
|
|
45
|
+
await test.step('accessibility', async () => {
|
|
46
|
+
await steps.automaticA11yCheckStep(componentsPage);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* VISUAL REGRESSION
|
|
51
|
+
*/
|
|
52
|
+
// TODO: fix visual regression test on CI
|
|
53
|
+
// await test.step('visual-regression', async () => {
|
|
54
|
+
// await test.step('matches screenshot of element', async () => {
|
|
55
|
+
// await componentsPage.visualRegression.takeScreenshot(`mdc-text-${textType}`, { element: text });
|
|
56
|
+
// });
|
|
57
|
+
// });
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* ATTRIBUTES
|
|
61
|
+
*/
|
|
62
|
+
await test.step('attributes', async () => {
|
|
63
|
+
if (isHeading(textType)) {
|
|
64
|
+
await test.step('attribute role=heading should be present on component if type is heading', async () => {
|
|
65
|
+
expect(await text.getAttribute('role')).toBe('heading');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
await test.step('attribute aria-level should be present on component if type is heading', async () => {
|
|
69
|
+
const expectedLevel = getAriaLevel(textType);
|
|
70
|
+
expect(await text.getAttribute('aria-level')).toBe(expectedLevel);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Meta, StoryObj, Args } from '@storybook/web-components';
|
|
2
|
+
import '.';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
import { VALUES } from './text.constants';
|
|
5
|
+
|
|
6
|
+
const render = (args: Args) => html`
|
|
7
|
+
<mdc-text type="${args.type}">${args.children}</mdc-text>
|
|
8
|
+
`;
|
|
9
|
+
|
|
10
|
+
const meta: Meta = {
|
|
11
|
+
tags: ['autodocs'],
|
|
12
|
+
component: 'mdc-text',
|
|
13
|
+
render,
|
|
14
|
+
argTypes: {
|
|
15
|
+
type: {
|
|
16
|
+
control: 'radio',
|
|
17
|
+
options: VALUES.TYPE,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
|
|
24
|
+
export const Primary: StoryObj = {
|
|
25
|
+
args: {
|
|
26
|
+
type: 'heading-1',
|
|
27
|
+
children: 'This is a test text',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
import { fontsStyles } from './fonts.styles';
|
|
3
|
+
|
|
4
|
+
const styles = [
|
|
5
|
+
css`
|
|
6
|
+
:host {
|
|
7
|
+
--mdc-text-font-family: var(--mdc-themeprovider-font-family);
|
|
8
|
+
|
|
9
|
+
display: block;
|
|
10
|
+
font-family: var(--mdc-text-font-family);
|
|
11
|
+
}
|
|
12
|
+
`,
|
|
13
|
+
// type specific font styles:
|
|
14
|
+
fontsStyles,
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
export default styles;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { FontType } from './text.types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Split the passed in type and return the parts
|
|
5
|
+
*/
|
|
6
|
+
const getTypeParts = (type: FontType) => {
|
|
7
|
+
const parts = type.split('-');
|
|
8
|
+
return { firstPart: parts[0], secondPart: parts[1] };
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Check if passed in type is a heading
|
|
13
|
+
* @param type - type to check
|
|
14
|
+
* @returns boolean, true if it is a heading
|
|
15
|
+
*/
|
|
16
|
+
const isHeading = (type: FontType) => {
|
|
17
|
+
const { firstPart, secondPart } = getTypeParts(type);
|
|
18
|
+
return firstPart === 'heading' && +secondPart > 0 && +secondPart < 7;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Get corresponding aria-role to type
|
|
23
|
+
* @param type - type to find corresponding role for
|
|
24
|
+
* @returns role
|
|
25
|
+
*/
|
|
26
|
+
const getRole = (type?: FontType) => {
|
|
27
|
+
if (type) {
|
|
28
|
+
if (isHeading(type)) {
|
|
29
|
+
return 'heading';
|
|
30
|
+
}
|
|
31
|
+
return 'paragraph';
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get corresponding aria-level to type
|
|
38
|
+
* @param type type to find corresponding level for
|
|
39
|
+
* @returns aria-level (has to be a number)
|
|
40
|
+
*/
|
|
41
|
+
const getAriaLevel = (type?: FontType) => {
|
|
42
|
+
if (type) {
|
|
43
|
+
if (isHeading(type)) {
|
|
44
|
+
const { secondPart } = getTypeParts(type);
|
|
45
|
+
return secondPart;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { isHeading, getAriaLevel, getRole };
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ThemeProvider from './themeprovider.component';
|
|
2
|
+
import { TAG_NAME } from './themeprovider.constants';
|
|
3
|
+
|
|
4
|
+
ThemeProvider.register(TAG_NAME);
|
|
5
|
+
|
|
6
|
+
declare global {
|
|
7
|
+
interface HTMLElementTagNameMap {
|
|
8
|
+
['mdc-themeprovider']: ThemeProvider
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default ThemeProvider;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { property } from 'lit/decorators.js';
|
|
2
|
+
import { DEFAULTS, THEMES } from './themeprovider.constants';
|
|
3
|
+
import { Provider } from '../../models';
|
|
4
|
+
import ThemeProviderContext from './themeprovider.context';
|
|
5
|
+
import styles from './themeprovider.styles';
|
|
6
|
+
import type { Theme } from './themeprovider.types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* ThemeProvider component, which sets the theme css variables
|
|
10
|
+
* for the child dom nodes and allows to be consumed from sub components
|
|
11
|
+
* (see providerUtils.consume for how to consume)
|
|
12
|
+
*
|
|
13
|
+
* ThemeProvider also includes the different font faces available
|
|
14
|
+
* for Text components.
|
|
15
|
+
*
|
|
16
|
+
* @tag mdc-themeprovider
|
|
17
|
+
* @tagname mdc-themeprovider
|
|
18
|
+
*/
|
|
19
|
+
class ThemeProvider extends Provider<ThemeProviderContext> {
|
|
20
|
+
constructor() {
|
|
21
|
+
// initialise the context by running the Provider constructor:
|
|
22
|
+
super({
|
|
23
|
+
context: ThemeProviderContext.context,
|
|
24
|
+
initialValue: new ThemeProviderContext(DEFAULTS.THEME),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public static get Context() {
|
|
29
|
+
return ThemeProviderContext.context;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Available themes to switch to
|
|
34
|
+
*
|
|
35
|
+
* Has to be a space separated string, like className
|
|
36
|
+
* e.g.: `mds-theme-stable-darkWebex mds-theme-stable-lightWebex`
|
|
37
|
+
*/
|
|
38
|
+
@property({ type: String })
|
|
39
|
+
themes: string = THEMES.join(' ');
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Current theme attribute
|
|
43
|
+
*
|
|
44
|
+
* Has to be fully qualified, such that
|
|
45
|
+
* the theme name matches the className of the respective
|
|
46
|
+
* theme stylesheet
|
|
47
|
+
*/
|
|
48
|
+
@property({ type: String })
|
|
49
|
+
theme: Theme = DEFAULTS.THEME;
|
|
50
|
+
|
|
51
|
+
protected override updated(changedProperties: Map<string, any>) {
|
|
52
|
+
super.updated(changedProperties);
|
|
53
|
+
|
|
54
|
+
if (changedProperties.has('theme')) {
|
|
55
|
+
this.updateActiveThemeClass();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Update all observing components of this
|
|
61
|
+
* provider to update the theme
|
|
62
|
+
*/
|
|
63
|
+
protected updateContext(): void {
|
|
64
|
+
let shouldUpdateConsumers = false;
|
|
65
|
+
|
|
66
|
+
if (this.context.value.theme !== this.theme) {
|
|
67
|
+
this.context.value.theme = this.theme;
|
|
68
|
+
|
|
69
|
+
shouldUpdateConsumers = true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (shouldUpdateConsumers) {
|
|
73
|
+
this.context.updateObservers();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Function to update the active theme classname to update the theme tokens
|
|
79
|
+
* as CSS variables on the web component.
|
|
80
|
+
*/
|
|
81
|
+
private updateActiveThemeClass() {
|
|
82
|
+
// remove all existing theme classes from the classList:
|
|
83
|
+
this.classList.remove(...this.themes.split(' '));
|
|
84
|
+
// add current theme class to classList:
|
|
85
|
+
this.classList.add(this.theme);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public static override styles = styles;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default ThemeProvider;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* eslint-disable implicit-arrow-linebreak */
|
|
2
|
+
import utils from '../../utils/tag-name';
|
|
3
|
+
import type { Theme } from './themeprovider.types';
|
|
4
|
+
import themeProviderUtils from './themeprovider.utils';
|
|
5
|
+
|
|
6
|
+
const TAG_NAME = utils.constructTagName('themeprovider');
|
|
7
|
+
|
|
8
|
+
// Some themes are disabled until tokens are available for those themes
|
|
9
|
+
const THEME_NAMES = {
|
|
10
|
+
// DARK_BRONZE: 'darkBronze' as const,
|
|
11
|
+
// DARK_INDIGO: 'darkIndigo' as const,
|
|
12
|
+
// DARK_JADE: 'darkJade' as const,
|
|
13
|
+
// DARK_LAVENDER: 'darkLavender' as const,
|
|
14
|
+
// DARK_ROSE: 'darkRose' as const,
|
|
15
|
+
DARK_WEBEX: 'darkWebex' as const,
|
|
16
|
+
// LIGHT_BRONZE: 'lightBronze' as const,
|
|
17
|
+
// LIGHT_INDIGO: 'lightIndigo' as const,
|
|
18
|
+
// LIGHT_JADE: 'lightJade' as const,
|
|
19
|
+
// LIGHT_LAVENDER: 'lightLavender' as const,
|
|
20
|
+
// LIGHT_ROSE: 'lightRose' as const,
|
|
21
|
+
LIGHT_WEBEX: 'lightWebex' as const,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const THEMES = Object.values(THEME_NAMES).map(
|
|
25
|
+
(themeName) => themeProviderUtils.getFullQualifiedTheme(themeName),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const DEFAULTS = {
|
|
29
|
+
THEME: themeProviderUtils.getFullQualifiedTheme(THEME_NAMES.DARK_WEBEX) as Theme<typeof THEME_NAMES.DARK_WEBEX>,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { DEFAULTS, THEME_NAMES, THEMES, TAG_NAME };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createContext } from '@lit-labs/context';
|
|
2
|
+
|
|
3
|
+
import { TAG_NAME } from './themeprovider.constants';
|
|
4
|
+
import type { Theme } from './themeprovider.types';
|
|
5
|
+
|
|
6
|
+
class ThemeProviderContext {
|
|
7
|
+
public theme?: Theme;
|
|
8
|
+
|
|
9
|
+
// create typed lit context as part of the ThemeProviderContext
|
|
10
|
+
public static context = createContext<ThemeProviderContext>(TAG_NAME);
|
|
11
|
+
|
|
12
|
+
// constructor to allow setting the defaultTheme
|
|
13
|
+
constructor(defaultTheme?: Theme) {
|
|
14
|
+
this.theme = defaultTheme;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default ThemeProviderContext;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { expect } from '@playwright/test';
|
|
2
|
+
import { ComponentsPage, test } from '../../../config/playwright/setup';
|
|
3
|
+
import steps from '../../../config/playwright/setup/steps/accessibility';
|
|
4
|
+
import { THEME_NAMES } from './themeprovider.constants';
|
|
5
|
+
import type { ThemeName } from './themeprovider.types';
|
|
6
|
+
import utils from './themeprovider.utils';
|
|
7
|
+
|
|
8
|
+
test.beforeEach(async ({ componentsPage, theme }) => {
|
|
9
|
+
const themeClass = utils.getFullQualifiedTheme(theme);
|
|
10
|
+
await componentsPage.mount({
|
|
11
|
+
html: `
|
|
12
|
+
<mdc-themeprovider class="themeWrapper" id="local" theme="${themeClass}">
|
|
13
|
+
<p>Current theme: ${themeClass}</p>
|
|
14
|
+
<div>
|
|
15
|
+
<div class="colorBox" style="background: var(--mds-color-theme-text-accent-normal);"></div>
|
|
16
|
+
<div class="colorBox" style="background: var(--mds-color-theme-text-warning-normal);"></div>
|
|
17
|
+
<div class="colorBox" style="background: var(--mds-color-theme-background-alert-success-normal);"></div>
|
|
18
|
+
</div>
|
|
19
|
+
</mdc-themeprovider>
|
|
20
|
+
`,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const testToRun = async (componentsPage: ComponentsPage, theme: ThemeName) => {
|
|
25
|
+
const themeprovider = componentsPage.page.locator('mdc-themeprovider#local');
|
|
26
|
+
|
|
27
|
+
// get fully qualified theme
|
|
28
|
+
const themeClass = utils.getFullQualifiedTheme(theme);
|
|
29
|
+
const oppositeThemeClass = themeClass.includes('darkWebex')
|
|
30
|
+
? utils.getFullQualifiedTheme('lightWebex')
|
|
31
|
+
: utils.getFullQualifiedTheme('darkWebex');
|
|
32
|
+
|
|
33
|
+
// initial check for the themeprovider be visible on the screen:
|
|
34
|
+
await themeprovider.waitFor();
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* ACCESSIBILITY
|
|
38
|
+
*/
|
|
39
|
+
await test.step('accessibility', async () => {
|
|
40
|
+
await steps.automaticA11yCheckStep(componentsPage);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* VISUAL REGRESSION
|
|
45
|
+
*/
|
|
46
|
+
// TODO: fix visual regression test on CI
|
|
47
|
+
// await test.step('visual-regression', async () => {
|
|
48
|
+
// await test.step('matches screenshot of element', async () => {
|
|
49
|
+
// await componentsPage.visualRegression.takeScreenshot(`mdc-themeprovider-${theme}`, {
|
|
50
|
+
// element: themeprovider,
|
|
51
|
+
// });
|
|
52
|
+
// });
|
|
53
|
+
// });
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* ATTRIBUTES
|
|
57
|
+
*/
|
|
58
|
+
await test.step('attributes', async () => {
|
|
59
|
+
await test.step('attribute theme should be present on component by default', async () => {
|
|
60
|
+
expect(await themeprovider.getAttribute('theme')).toBe(themeClass);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
await test.step('corresponding theme class should be present on component by default', async () => {
|
|
64
|
+
expect(await themeprovider.getAttribute('class')).toContain(themeClass);
|
|
65
|
+
expect(await themeprovider.getAttribute('class')).not.toContain(oppositeThemeClass);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// test.describe('mdc-themeprovider', () => {
|
|
71
|
+
// test.use({
|
|
72
|
+
// theme: THEME_NAMES.DARK_WEBEX,
|
|
73
|
+
// });
|
|
74
|
+
|
|
75
|
+
// test('dark', async ({ componentsPage, theme }) => {
|
|
76
|
+
// await testToRun(componentsPage, theme);
|
|
77
|
+
// });
|
|
78
|
+
// });
|
|
79
|
+
|
|
80
|
+
test.describe('mdc-themeprovider', () => {
|
|
81
|
+
test.use({
|
|
82
|
+
theme: THEME_NAMES.LIGHT_WEBEX,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// TODO: fix e2e test
|
|
86
|
+
test.fixme('light', async ({ componentsPage, theme }) => {
|
|
87
|
+
await testToRun(componentsPage, theme);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.themeWrapper {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
width: calc(30%);
|
|
5
|
+
background: var(--mds-color-theme-background-solid-primary-normal);
|
|
6
|
+
padding: 10px;
|
|
7
|
+
border: 1px solid var(--mds-color-theme-text-primary-normal)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.themeWrapper+.themeWrapper {
|
|
11
|
+
margin-top: 10px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.colorBox {
|
|
15
|
+
width: 100%;
|
|
16
|
+
height: 10px;
|
|
17
|
+
border-radius: 5px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.colorBox+.colorBox {
|
|
21
|
+
margin-top: 10px;
|
|
22
|
+
}
|