@grantcodes/ui 2.15.6 → 2.16.0
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/CHANGELOG.md +67 -0
- package/custom-elements.json +476 -346
- package/package.json +23 -23
- package/src/components/accordion/accordion-item.component.js +17 -19
- package/src/components/accordion/accordion-item.css +40 -44
- package/src/components/accordion/accordion.component.js +7 -7
- package/src/components/accordion/accordion.css +5 -5
- package/src/components/accordion/accordion.js +6 -6
- package/src/components/accordion/accordion.react.js +6 -6
- package/src/components/accordion/accordion.stories.js +10 -10
- package/src/components/accordion/accordion.test.js +100 -100
- package/src/components/accordion/index.js +6 -6
- package/src/components/app-bar/app-bar.component.js +86 -92
- package/src/components/app-bar/app-bar.css +187 -203
- package/src/components/app-bar/app-bar.js +3 -3
- package/src/components/app-bar/app-bar.react.js +9 -9
- package/src/components/app-bar/app-bar.stories.js +20 -20
- package/src/components/app-bar/app-bar.test.js +190 -237
- package/src/components/app-bar/index.js +1 -1
- package/src/components/app-bar/nav-link.component.js +7 -9
- package/src/components/app-bar/nav-link.css +23 -28
- package/src/components/app-bar/nav-link.js +3 -3
- package/src/components/app-bar/nav-link.react.js +6 -6
- package/src/components/avatar/avatar.component.js +79 -68
- package/src/components/avatar/avatar.css +18 -18
- package/src/components/avatar/avatar.js +3 -3
- package/src/components/avatar/avatar.react.js +6 -6
- package/src/components/avatar/avatar.stories.js +24 -23
- package/src/components/avatar/avatar.test.js +128 -84
- package/src/components/avatar/index.js +1 -1
- package/src/components/badge/badge.component.js +23 -23
- package/src/components/badge/badge.css +39 -52
- package/src/components/badge/badge.js +3 -3
- package/src/components/badge/badge.react.js +6 -6
- package/src/components/badge/badge.stories.js +23 -23
- package/src/components/badge/badge.test.js +53 -68
- package/src/components/badge/index.js +1 -1
- package/src/components/breadcrumb/breadcrumb.component.js +95 -96
- package/src/components/breadcrumb/breadcrumb.css +42 -44
- package/src/components/breadcrumb/breadcrumb.js +6 -9
- package/src/components/breadcrumb/breadcrumb.react.js +9 -12
- package/src/components/breadcrumb/breadcrumb.stories.js +5 -5
- package/src/components/breadcrumb/breadcrumb.test.js +139 -151
- package/src/components/breadcrumb/index.js +1 -1
- package/src/components/button/button.component.js +101 -103
- package/src/components/button/button.css +90 -94
- package/src/components/button/button.js +3 -3
- package/src/components/button/button.react.js +6 -6
- package/src/components/button/button.stories.js +25 -25
- package/src/components/button/button.test.js +324 -344
- package/src/components/button/index.js +1 -1
- package/src/components/button-group/button-group.component.js +18 -18
- package/src/components/button-group/button-group.css +16 -16
- package/src/components/button-group/button-group.js +3 -3
- package/src/components/button-group/button-group.react.js +6 -6
- package/src/components/button-group/button-group.stories.js +23 -23
- package/src/components/button-group/button-group.test.js +54 -54
- package/src/components/button-group/index.js +1 -1
- package/src/components/card/card.component.js +31 -33
- package/src/components/card/card.css +85 -85
- package/src/components/card/card.js +4 -4
- package/src/components/card/card.react.js +6 -6
- package/src/components/card/card.stories.js +27 -26
- package/src/components/card/card.test.js +56 -56
- package/src/components/card/index.js +1 -1
- package/src/components/code-preview/code-preview.component.js +47 -48
- package/src/components/code-preview/code-preview.css +11 -11
- package/src/components/code-preview/code-preview.js +3 -3
- package/src/components/code-preview/code-preview.react.js +6 -6
- package/src/components/code-preview/code-preview.stories.js +29 -29
- package/src/components/code-preview/code-preview.test.js +112 -135
- package/src/components/code-preview/index.js +1 -1
- package/src/components/container/container.component.js +27 -27
- package/src/components/container/container.css +22 -22
- package/src/components/container/container.js +3 -3
- package/src/components/container/container.react.js +6 -6
- package/src/components/container/container.stories.js +44 -44
- package/src/components/container/container.test.js +54 -66
- package/src/components/container/index.js +1 -1
- package/src/components/countdown/countdown.component.js +160 -162
- package/src/components/countdown/countdown.css +50 -34
- package/src/components/countdown/countdown.js +3 -3
- package/src/components/countdown/countdown.react.js +6 -6
- package/src/components/countdown/countdown.stories.js +34 -34
- package/src/components/countdown/index.js +1 -1
- package/src/components/cta/cta.component.js +77 -81
- package/src/components/cta/cta.css +24 -24
- package/src/components/cta/cta.js +3 -3
- package/src/components/cta/cta.react.js +6 -6
- package/src/components/cta/cta.stories.js +32 -32
- package/src/components/cta/index.js +1 -1
- package/src/components/dialog/dialog.component.js +95 -58
- package/src/components/dialog/dialog.css +45 -50
- package/src/components/dialog/dialog.js +3 -3
- package/src/components/dialog/dialog.react.js +6 -6
- package/src/components/dialog/dialog.stories.js +38 -29
- package/src/components/dialog/dialog.test.js +188 -102
- package/src/components/dialog/index.js +1 -1
- package/src/components/dropdown/dropdown.component.js +220 -201
- package/src/components/dropdown/dropdown.css +60 -84
- package/src/components/dropdown/dropdown.js +6 -9
- package/src/components/dropdown/dropdown.react.js +15 -15
- package/src/components/dropdown/dropdown.stories.js +10 -10
- package/src/components/dropdown/dropdown.test.js +211 -157
- package/src/components/dropdown/index.js +1 -1
- package/src/components/dropzone/dropzone.component.js +126 -129
- package/src/components/dropzone/dropzone.css +35 -37
- package/src/components/dropzone/dropzone.js +3 -3
- package/src/components/dropzone/dropzone.react.js +6 -6
- package/src/components/dropzone/dropzone.stories.js +28 -28
- package/src/components/dropzone/dropzone.test.js +91 -99
- package/src/components/dropzone/index.js +1 -1
- package/src/components/feature-list/feature-list.component.js +78 -86
- package/src/components/feature-list/feature-list.css +37 -37
- package/src/components/feature-list/feature-list.js +3 -3
- package/src/components/feature-list/feature-list.react.js +6 -6
- package/src/components/feature-list/feature-list.stories.js +86 -90
- package/src/components/feature-list/index.js +1 -1
- package/src/components/footer/footer-column.component.js +7 -7
- package/src/components/footer/footer-column.css +22 -22
- package/src/components/footer/footer.component.js +19 -19
- package/src/components/footer/footer.css +38 -38
- package/src/components/footer/footer.js +8 -8
- package/src/components/footer/footer.react.js +9 -9
- package/src/components/footer/footer.stories.js +9 -9
- package/src/components/footer/footer.test.js +101 -111
- package/src/components/footer/index.js +2 -2
- package/src/components/form-field/form-field.component.js +167 -125
- package/src/components/form-field/form-field.css +24 -24
- package/src/components/form-field/form-field.js +3 -3
- package/src/components/form-field/form-field.react.js +6 -6
- package/src/components/form-field/form-field.stories.js +53 -44
- package/src/components/form-field/form-field.test.js +280 -134
- package/src/components/form-field/index.js +1 -1
- package/src/components/gallery/gallery-image.component.js +30 -30
- package/src/components/gallery/gallery-image.js +3 -3
- package/src/components/gallery/gallery-image.react.js +6 -6
- package/src/components/gallery/gallery.component.js +24 -17
- package/src/components/gallery/gallery.css +79 -72
- package/src/components/gallery/gallery.js +3 -3
- package/src/components/gallery/gallery.react.js +6 -6
- package/src/components/gallery/gallery.stories.js +69 -68
- package/src/components/gallery/gallery.test.js +95 -88
- package/src/components/gallery/index.js +2 -2
- package/src/components/hero/hero.component.js +53 -57
- package/src/components/hero/hero.css +27 -27
- package/src/components/hero/hero.js +3 -3
- package/src/components/hero/hero.react.js +6 -6
- package/src/components/hero/hero.stories.js +39 -39
- package/src/components/hero/index.js +1 -1
- package/src/components/icon/icon.component.js +10 -10
- package/src/components/icon/icon.css +13 -13
- package/src/components/icon/icon.js +4 -4
- package/src/components/icon/icon.react.js +6 -6
- package/src/components/icon/icon.stories.js +8 -9
- package/src/components/icon/icon.test.js +54 -55
- package/src/components/icon/index.js +1 -1
- package/src/components/loading/index.js +1 -1
- package/src/components/loading/loading.component.js +41 -14
- package/src/components/loading/loading.css +47 -30
- package/src/components/loading/loading.js +4 -4
- package/src/components/loading/loading.react.js +6 -6
- package/src/components/loading/loading.stories.js +19 -18
- package/src/components/loading/loading.test.js +77 -54
- package/src/components/logo-cloud/index.js +1 -1
- package/src/components/logo-cloud/logo-cloud.component.js +39 -43
- package/src/components/logo-cloud/logo-cloud.css +31 -31
- package/src/components/logo-cloud/logo-cloud.js +3 -3
- package/src/components/logo-cloud/logo-cloud.react.js +6 -6
- package/src/components/logo-cloud/logo-cloud.stories.js +80 -80
- package/src/components/map/index.js +1 -1
- package/src/components/map/map.component.js +103 -107
- package/src/components/map/map.css +22 -22
- package/src/components/map/map.js +3 -3
- package/src/components/map/map.react.js +6 -6
- package/src/components/map/map.stories.js +38 -38
- package/src/components/media-text/index.js +1 -1
- package/src/components/media-text/media-text.component.js +76 -70
- package/src/components/media-text/media-text.css +32 -32
- package/src/components/media-text/media-text.js +3 -3
- package/src/components/media-text/media-text.react.js +6 -6
- package/src/components/media-text/media-text.stories.js +45 -45
- package/src/components/media-text/media-text.test.js +72 -0
- package/src/components/newsletter/index.js +1 -1
- package/src/components/newsletter/newsletter.component.js +56 -64
- package/src/components/newsletter/newsletter.css +48 -48
- package/src/components/newsletter/newsletter.js +3 -3
- package/src/components/newsletter/newsletter.react.js +6 -6
- package/src/components/newsletter/newsletter.stories.js +35 -35
- package/src/components/notice/index.js +1 -1
- package/src/components/notice/notice.component.js +66 -55
- package/src/components/notice/notice.css +37 -38
- package/src/components/notice/notice.js +3 -3
- package/src/components/notice/notice.react.js +6 -6
- package/src/components/notice/notice.stories.js +54 -53
- package/src/components/notice/notice.test.js +210 -156
- package/src/components/pagination/index.js +1 -1
- package/src/components/pagination/pagination.component.js +44 -44
- package/src/components/pagination/pagination.css +6 -6
- package/src/components/pagination/pagination.js +4 -4
- package/src/components/pagination/pagination.react.js +6 -6
- package/src/components/pagination/pagination.stories.js +20 -18
- package/src/components/pagination/pagination.test.js +95 -102
- package/src/components/person/index.js +1 -1
- package/src/components/person/person.component.js +29 -29
- package/src/components/person/person.css +17 -17
- package/src/components/person/person.js +4 -4
- package/src/components/person/person.react.js +6 -6
- package/src/components/person/person.stories.js +34 -33
- package/src/components/person/person.test.js +55 -68
- package/src/components/pricing/index.js +1 -1
- package/src/components/pricing/pricing.component.js +58 -70
- package/src/components/pricing/pricing.css +65 -65
- package/src/components/pricing/pricing.js +3 -3
- package/src/components/pricing/pricing.react.js +6 -6
- package/src/components/pricing/pricing.stories.js +96 -96
- package/src/components/sidebar/index.js +1 -1
- package/src/components/sidebar/sidebar.component.js +157 -130
- package/src/components/sidebar/sidebar.css +118 -115
- package/src/components/sidebar/sidebar.js +4 -4
- package/src/components/sidebar/sidebar.react.js +10 -10
- package/src/components/sidebar/sidebar.stories.js +10 -10
- package/src/components/sidebar/sidebar.test.js +250 -230
- package/src/components/stats/index.js +1 -1
- package/src/components/stats/stats.component.js +42 -50
- package/src/components/stats/stats.css +29 -29
- package/src/components/stats/stats.js +3 -3
- package/src/components/stats/stats.react.js +6 -6
- package/src/components/stats/stats.stories.js +40 -40
- package/src/components/tabs/index.js +2 -2
- package/src/components/tabs/internal/tabs-button.component.js +16 -27
- package/src/components/tabs/internal/tabs-button.js +3 -3
- package/src/components/tabs/internal/tabs-button.react.js +6 -6
- package/src/components/tabs/internal/tabs-item.component.js +30 -30
- package/src/components/tabs/tab.component.js +9 -11
- package/src/components/tabs/tab.js +3 -3
- package/src/components/tabs/tab.react.js +6 -6
- package/src/components/tabs/tabs.component.js +107 -109
- package/src/components/tabs/tabs.css +50 -59
- package/src/components/tabs/tabs.js +4 -4
- package/src/components/tabs/tabs.react.js +6 -6
- package/src/components/tabs/tabs.stories.js +23 -22
- package/src/components/tabs/tabs.test.js +201 -147
- package/src/components/testimonials/index.js +1 -1
- package/src/components/testimonials/testimonials.component.js +47 -51
- package/src/components/testimonials/testimonials.css +31 -31
- package/src/components/testimonials/testimonials.js +3 -3
- package/src/components/testimonials/testimonials.react.js +6 -6
- package/src/components/testimonials/testimonials.stories.js +49 -51
- package/src/components/toast/index.js +1 -1
- package/src/components/toast/toast.component.js +217 -148
- package/src/components/toast/toast.css +101 -99
- package/src/components/toast/toast.js +6 -9
- package/src/components/toast/toast.react.js +12 -12
- package/src/components/toast/toast.stories.js +75 -49
- package/src/components/toast/toast.test.js +260 -221
- package/src/components/tooltip/index.js +1 -1
- package/src/components/tooltip/tooltip.component.js +56 -49
- package/src/components/tooltip/tooltip.css +61 -50
- package/src/components/tooltip/tooltip.js +4 -4
- package/src/components/tooltip/tooltip.react.js +6 -6
- package/src/components/tooltip/tooltip.stories.js +24 -23
- package/src/components/tooltip/tooltip.test.js +143 -155
- package/src/constructor.test.js +31 -0
- package/src/css/base.css +1 -0
- package/src/css/colors.stories.js +120 -122
- package/src/css/elements/a.css +28 -28
- package/src/css/elements/forms/button.css +1 -1
- package/src/css/elements/forms/input.css +80 -80
- package/src/css/elements/forms/label.css +3 -3
- package/src/css/elements/media/image.css +2 -2
- package/src/css/elements.stories.js +48 -49
- package/src/css/helpers.css +8 -8
- package/src/css/layers.stories.js +5 -5
- package/src/css/reset.css +102 -102
- package/src/css/themes/todomap.css +1 -1
- package/src/css/tokens.stories.js +50 -53
- package/src/css/typography.css +30 -32
- package/src/css/typography.stories.js +92 -92
- package/src/css/util/focus-ring.css +12 -20
- package/src/css/view-transitions.css +16 -0
- package/src/exports.test.js +89 -105
- package/src/icons.js +1 -1
- package/src/lib/generate-id.js +1 -1
- package/src/lib/slot-presence-controller.js +48 -0
- package/src/lib/styles/all.css +38 -37
- package/src/lib/styles/focus-ring.css +12 -20
- package/src/lib/view-transition.js +42 -0
- package/src/lib/view-transition.test.js +105 -0
- package/src/main.js +29 -29
- package/src/pages/agency.stories.js +59 -59
- package/src/pages/blog-post.stories.js +48 -48
- package/src/pages/saas-landing.stories.js +180 -180
- package/src/react.js +44 -44
- package/src/react.test.js +42 -51
- package/src/test-utils/assert-helpers.js +39 -58
- package/src/test-utils/events.js +32 -34
- package/src/test-utils/fixture.js +31 -31
- package/src/test-utils/index.js +3 -3
- package/src/types.d.ts +3 -3
|
@@ -1,224 +1,263 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
describe(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
1
|
+
import { strict as assert } from 'node:assert';
|
|
2
|
+
import { afterEach, describe, it } from 'node:test';
|
|
3
|
+
import { cleanup, click, fixture } from '../../test-utils/index.js';
|
|
4
|
+
import './toast.js';
|
|
5
|
+
|
|
6
|
+
describe('Toast Component', () => {
|
|
7
|
+
let element;
|
|
8
|
+
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
cleanup(element);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it('should render with default properties', async () => {
|
|
14
|
+
element = await fixture('grantcodes-toast');
|
|
15
|
+
assert.ok(element, 'Element should be created');
|
|
16
|
+
assert.ok(element.shadowRoot, 'Element should have shadow root');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should have info variant by default', async () => {
|
|
20
|
+
element = await fixture('grantcodes-toast');
|
|
21
|
+
assert.strictEqual(element.variant, 'info', 'Default variant should be info');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should have 5000ms duration by default', async () => {
|
|
25
|
+
element = await fixture('grantcodes-toast');
|
|
26
|
+
assert.strictEqual(element.duration, 5000, 'Default duration should be 5000ms');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should have top-right position by default', async () => {
|
|
30
|
+
element = await fixture('grantcodes-toast');
|
|
31
|
+
assert.strictEqual(element.position, 'top-right', 'Default position should be top-right');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should be dismissible by default', async () => {
|
|
35
|
+
element = await fixture('grantcodes-toast');
|
|
36
|
+
assert.strictEqual(element.dismissible, true, 'Should be dismissible by default');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should render toast with correct variant class', async () => {
|
|
40
|
+
element = await fixture('grantcodes-toast', {
|
|
41
|
+
variant: 'success',
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const toast = element.shadowRoot.querySelector('.toast--success');
|
|
45
|
+
assert.ok(toast, 'Toast should have success variant class');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should render title when provided', async () => {
|
|
49
|
+
element = await fixture('grantcodes-toast', {
|
|
50
|
+
title: 'Test Title',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const title = element.shadowRoot.querySelector('.toast__title');
|
|
54
|
+
assert.ok(title, 'Title element should exist');
|
|
55
|
+
assert.strictEqual(title.textContent, 'Test Title', 'Title text should match');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should not render title when not provided', async () => {
|
|
59
|
+
element = await fixture('grantcodes-toast');
|
|
60
|
+
|
|
61
|
+
const title = element.shadowRoot.querySelector('.toast__title');
|
|
62
|
+
assert.ok(!title, 'Title element should not exist');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should render dismiss button when dismissible', async () => {
|
|
66
|
+
element = await fixture('grantcodes-toast', {
|
|
67
|
+
dismissible: true,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const closeButton = element.shadowRoot.querySelector('.toast__close');
|
|
71
|
+
assert.ok(closeButton, 'Close button should exist');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should not render dismiss button when not dismissible', async () => {
|
|
75
|
+
element = await fixture('grantcodes-toast', {
|
|
76
|
+
dismissible: false,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const closeButton = element.shadowRoot.querySelector('.toast__close');
|
|
80
|
+
assert.ok(!closeButton, 'Close button should not exist');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('should have role=status', async () => {
|
|
84
|
+
element = await fixture('grantcodes-toast');
|
|
85
|
+
|
|
86
|
+
const toast = element.shadowRoot.querySelector('.toast');
|
|
87
|
+
assert.strictEqual(toast.getAttribute('role'), 'status', 'Should have status role');
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should have aria-live=polite', async () => {
|
|
91
|
+
element = await fixture('grantcodes-toast');
|
|
92
|
+
|
|
93
|
+
const toast = element.shadowRoot.querySelector('.toast');
|
|
94
|
+
assert.strictEqual(toast.getAttribute('aria-live'), 'polite', 'Should have aria-live polite');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should render icon based on variant', async () => {
|
|
98
|
+
element = await fixture('grantcodes-toast', {
|
|
99
|
+
variant: 'success',
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const icon = element.shadowRoot.querySelector('.toast__icon');
|
|
103
|
+
assert.ok(icon, 'Icon should exist');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should emit dismiss event when dismissed', async () => {
|
|
107
|
+
element = await fixture('grantcodes-toast', {
|
|
108
|
+
dismissible: true,
|
|
109
|
+
duration: 0, // Disable auto-dismiss
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
let dismissed = false;
|
|
113
|
+
element.addEventListener('dismiss', () => {
|
|
114
|
+
dismissed = true;
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const closeButton = element.shadowRoot.querySelector('.toast__close');
|
|
118
|
+
click(closeButton);
|
|
119
|
+
|
|
120
|
+
// Wait a bit for animation
|
|
121
|
+
await new Promise((resolve) => setTimeout(resolve, 350));
|
|
122
|
+
|
|
123
|
+
assert.ok(dismissed, 'Dismiss event should have fired');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('should support all variant types', async () => {
|
|
127
|
+
const variants = ['info', 'success', 'warning', 'error'];
|
|
128
|
+
|
|
129
|
+
for (const variant of variants) {
|
|
130
|
+
element = await fixture('grantcodes-toast', { variant });
|
|
131
|
+
const toast = element.shadowRoot.querySelector(`.toast--${variant}`);
|
|
132
|
+
assert.ok(toast, `Toast should have ${variant} variant class`);
|
|
133
|
+
cleanup(element);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('should announce errors assertively and other variants politely', async () => {
|
|
138
|
+
element = await fixture('grantcodes-toast', { variant: 'error' });
|
|
139
|
+
|
|
140
|
+
const errorToast = element.shadowRoot.querySelector('.toast--error');
|
|
141
|
+
assert.strictEqual(errorToast.getAttribute('role'), 'alert', 'Errors should interrupt');
|
|
142
|
+
assert.strictEqual(errorToast.getAttribute('aria-live'), 'assertive');
|
|
143
|
+
|
|
144
|
+
const info = await fixture('grantcodes-toast', { variant: 'info' });
|
|
145
|
+
const infoToast = info.shadowRoot.querySelector('.toast--info');
|
|
146
|
+
assert.strictEqual(infoToast.getAttribute('role'), 'status', 'Other variants should wait');
|
|
147
|
+
assert.strictEqual(infoToast.getAttribute('aria-live'), 'polite');
|
|
148
|
+
cleanup(info);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should hold the toast open while it is hovered', async () => {
|
|
152
|
+
element = await fixture('grantcodes-toast', { duration: 60 });
|
|
153
|
+
|
|
154
|
+
const toast = element.shadowRoot.querySelector('.toast');
|
|
155
|
+
toast.dispatchEvent(new Event('mouseenter'));
|
|
156
|
+
await new Promise((resolve) => setTimeout(resolve, 120));
|
|
157
|
+
|
|
158
|
+
assert.ok(element.isConnected, 'A hovered toast must not auto-dismiss');
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('should restart the auto-dismiss timer when the pointer leaves', async () => {
|
|
162
|
+
element = await fixture('grantcodes-toast', { duration: 60 });
|
|
163
|
+
|
|
164
|
+
const toast = element.shadowRoot.querySelector('.toast');
|
|
165
|
+
toast.dispatchEvent(new Event('mouseenter'));
|
|
166
|
+
await new Promise((resolve) => setTimeout(resolve, 40));
|
|
167
|
+
toast.dispatchEvent(new Event('mouseleave'));
|
|
168
|
+
await new Promise((resolve) => setTimeout(resolve, 400));
|
|
169
|
+
|
|
170
|
+
assert.strictEqual(
|
|
171
|
+
element.isConnected,
|
|
172
|
+
false,
|
|
173
|
+
'Toast should dismiss once the pointer leaves',
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should skip the exit animation when reduced motion is preferred', async () => {
|
|
178
|
+
element = await fixture('grantcodes-toast', { duration: 0 });
|
|
179
|
+
|
|
180
|
+
const originalMatchMedia = globalThis.window.matchMedia;
|
|
181
|
+
globalThis.window.matchMedia = () => ({ matches: true });
|
|
182
|
+
|
|
183
|
+
click(element.shadowRoot.querySelector('.toast__close'));
|
|
184
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
185
|
+
globalThis.window.matchMedia = originalMatchMedia;
|
|
186
|
+
|
|
187
|
+
assert.strictEqual(element.isConnected, false, 'No exit animation to wait for');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should dismiss through a view transition when motion is allowed', async () => {
|
|
191
|
+
const originalMatchMedia = globalThis.window.matchMedia;
|
|
192
|
+
const originalStartViewTransition = globalThis.document.startViewTransition;
|
|
193
|
+
let transitions = 0;
|
|
194
|
+
globalThis.window.matchMedia = () => ({ matches: false });
|
|
195
|
+
globalThis.document.startViewTransition = (callback) => {
|
|
196
|
+
transitions++;
|
|
197
|
+
callback();
|
|
198
|
+
return { finished: Promise.resolve() };
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
element = await fixture('grantcodes-toast', { dismissible: true, duration: 0 });
|
|
202
|
+
click(element.shadowRoot.querySelector('.toast__close'));
|
|
203
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
204
|
+
|
|
205
|
+
globalThis.window.matchMedia = originalMatchMedia;
|
|
206
|
+
globalThis.document.startViewTransition = originalStartViewTransition;
|
|
207
|
+
|
|
208
|
+
assert.strictEqual(transitions, 2, 'Enter and exit should both animate');
|
|
209
|
+
assert.strictEqual(element.isConnected, false, 'Toast should be removed');
|
|
210
|
+
});
|
|
164
211
|
});
|
|
165
212
|
|
|
166
|
-
describe(
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
element = await fixture("grantcodes-toast-container", { position });
|
|
217
|
-
const container = element.shadowRoot.querySelector(
|
|
218
|
-
`.toast-container--${position}`,
|
|
219
|
-
);
|
|
220
|
-
assert.ok(container, `Container should have ${position} position class`);
|
|
221
|
-
cleanup(element);
|
|
222
|
-
}
|
|
223
|
-
});
|
|
213
|
+
describe('Toast Container Component', () => {
|
|
214
|
+
let element;
|
|
215
|
+
|
|
216
|
+
afterEach(() => {
|
|
217
|
+
cleanup(element);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should render toast container', async () => {
|
|
221
|
+
element = await fixture('grantcodes-toast-container');
|
|
222
|
+
assert.ok(element, 'Element should be created');
|
|
223
|
+
assert.ok(element.shadowRoot, 'Element should have shadow root');
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
it('should have top-right position by default', async () => {
|
|
227
|
+
element = await fixture('grantcodes-toast-container');
|
|
228
|
+
assert.strictEqual(element.position, 'top-right', 'Default position should be top-right');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('should render container with correct position class', async () => {
|
|
232
|
+
element = await fixture('grantcodes-toast-container', {
|
|
233
|
+
position: 'bottom-left',
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
const container = element.shadowRoot.querySelector('.toast-container--bottom-left');
|
|
237
|
+
assert.ok(container, 'Container should have bottom-left position class');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('should have slot for toast items', async () => {
|
|
241
|
+
element = await fixture('grantcodes-toast-container');
|
|
242
|
+
const slot = element.shadowRoot.querySelector('slot');
|
|
243
|
+
assert.ok(slot, 'Slot should exist for toast items');
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should support all position types', async () => {
|
|
247
|
+
const positions = [
|
|
248
|
+
'top-left',
|
|
249
|
+
'top-center',
|
|
250
|
+
'top-right',
|
|
251
|
+
'bottom-left',
|
|
252
|
+
'bottom-center',
|
|
253
|
+
'bottom-right',
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
for (const position of positions) {
|
|
257
|
+
element = await fixture('grantcodes-toast-container', { position });
|
|
258
|
+
const container = element.shadowRoot.querySelector(`.toast-container--${position}`);
|
|
259
|
+
assert.ok(container, `Container should have ${position} position class`);
|
|
260
|
+
cleanup(element);
|
|
261
|
+
}
|
|
262
|
+
});
|
|
224
263
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from
|
|
1
|
+
export * from './tooltip.js';
|
|
@@ -1,62 +1,69 @@
|
|
|
1
|
-
import { LitElement } from
|
|
2
|
-
import { html } from
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { html } from 'lit/static-html.js';
|
|
3
|
+
import { generateId } from '../../lib/generate-id.js';
|
|
4
|
+
import tooltipStyles from './tooltip.css' with { type: 'css' };
|
|
5
5
|
|
|
6
6
|
export class GrantCodesTooltip extends LitElement {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
// Styles are scoped to this element: they won't conflict with styles
|
|
8
|
+
// on the main page or in other components. Styling API can be exposed
|
|
9
|
+
// via CSS custom properties.
|
|
10
|
+
static styles = [tooltipStyles];
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
static properties = {
|
|
13
|
+
label: { type: String },
|
|
14
|
+
description: { type: String },
|
|
15
|
+
};
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.label = "";
|
|
20
|
+
/**
|
|
21
|
+
* Label for the tooltip, used when the tooltip is the main label for the item.
|
|
22
|
+
*/
|
|
23
|
+
this.label = '';
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Description for the tooltip, used when the tooltip is additional descriptive text for the item.
|
|
27
|
+
*/
|
|
28
|
+
this.description = '';
|
|
29
|
+
}
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
/** @type {Element[]} */
|
|
32
|
+
slotted = [];
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (tooltipSlot) {
|
|
43
|
-
tooltipSlot.style.anchorName = `--tooltip-${this.id}`;
|
|
44
|
-
}
|
|
34
|
+
connectedCallback() {
|
|
35
|
+
super.connectedCallback();
|
|
36
|
+
// Not in the constructor: a custom element that gains an attribute there is never upgraded.
|
|
37
|
+
if (!this.id) {
|
|
38
|
+
this.id = generateId('tooltip');
|
|
39
|
+
}
|
|
40
|
+
}
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
firstUpdated() {
|
|
43
|
+
const slot = this.renderRoot.querySelector('slot');
|
|
44
|
+
this.slotted = slot ? slot.assignedElements() : [];
|
|
45
|
+
const labeledElement = this.slotted[0];
|
|
46
|
+
if (labeledElement) {
|
|
47
|
+
// Set up anchor name for CSS anchor positioning
|
|
48
|
+
const tooltipSlot = this.renderRoot.querySelector('.tooltip__slot');
|
|
49
|
+
if (tooltipSlot) {
|
|
50
|
+
tooltipSlot.style.anchorName = `--tooltip-${this.id}`;
|
|
51
|
+
}
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
if (this.label) {
|
|
54
|
+
labeledElement.setAttribute('aria-labelledby', this.id);
|
|
55
|
+
} else if (this.description) {
|
|
56
|
+
labeledElement.setAttribute('aria-describedby', this.id);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
58
60
|
|
|
59
|
-
|
|
61
|
+
render() {
|
|
62
|
+
if (this.label && this.description) {
|
|
63
|
+
throw new Error('You cannot provide both a label and a description');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return html`
|
|
60
67
|
<div class="tooltip">
|
|
61
68
|
<div class="tooltip__slot">
|
|
62
69
|
<slot></slot>
|
|
@@ -66,5 +73,5 @@ export class GrantCodesTooltip extends LitElement {
|
|
|
66
73
|
</p>
|
|
67
74
|
</div>
|
|
68
75
|
`;
|
|
69
|
-
|
|
76
|
+
}
|
|
70
77
|
}
|