@stackoverflow/stacks 1.6.7 → 1.7.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/README.md +39 -0
- package/dist/controllers/index.d.ts +2 -0
- package/dist/controllers/s-banner.d.ts +41 -0
- package/dist/controllers/s-toast.d.ts +97 -0
- package/dist/css/stacks.css +18930 -18921
- package/dist/css/stacks.min.css +1 -1
- package/dist/js/stacks.js +5252 -5260
- package/dist/js/stacks.min.js +1 -1
- package/dist/stacks.d.ts +1 -1
- package/lib/css/components/anchors.less +61 -0
- package/lib/css/components/block-link.less +80 -0
- package/lib/css/components/buttons.less +12 -0
- package/lib/css/components/inputs.less +4 -0
- package/lib/css/components/link.less +112 -0
- package/lib/css/components/post-summary.less +330 -355
- package/lib/css/components/table.less +297 -0
- package/lib/css/stacks-dynamic.less +0 -8
- package/lib/css/stacks-static.less +9 -1
- package/lib/test/s-avatar.test.ts +74 -0
- package/lib/test/s-banner.test.ts +73 -0
- package/lib/test/s-banner.visual.test.ts +61 -0
- package/lib/test/s-button.visual.test.ts +12 -0
- package/lib/test/s-toast.test.ts +63 -0
- package/lib/test/s-toast.visual.test.ts +48 -0
- package/lib/ts/controllers/index.ts +2 -0
- package/lib/ts/controllers/s-banner.ts +149 -0
- package/lib/ts/controllers/s-toast.ts +357 -0
- package/lib/ts/index.ts +4 -0
- package/lib/ts/stacks.ts +1 -1
- package/lib/tsconfig.json +2 -2
- package/package.json +15 -15
- package/lib/css/components/links.less +0 -214
- package/lib/css/components/tables.less +0 -313
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
.s-table-container {
|
|
2
|
+
overflow-x: auto;
|
|
3
|
+
@scrollbar-styles();
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.s-table {
|
|
7
|
+
@ta-cell-border: var(--su-static1) solid var(--bc-medium);
|
|
8
|
+
@ta-columns: (100% / 12);
|
|
9
|
+
|
|
10
|
+
--_ta-tbody-tbody-bc: var(--bc-medium);
|
|
11
|
+
--_ta-tbody-tbody-bw: var(--su-static2);
|
|
12
|
+
--_ta-tbody-tr-even-bg: unset;
|
|
13
|
+
--_ta-td-bbw: 0;
|
|
14
|
+
--_ta-td-bc: var(--bc-medium);
|
|
15
|
+
--_ta-td-fs: unset;
|
|
16
|
+
--_ta-td-fw: unset;
|
|
17
|
+
--_ta-td-p: var(--su8);
|
|
18
|
+
--_ta-td-ta: left;
|
|
19
|
+
--_ta-td-va: middle;
|
|
20
|
+
--_ta-td-w: unset;
|
|
21
|
+
--_ta-thead-th-bg: var(--black-025);
|
|
22
|
+
--_ta-th-bbw: 0;
|
|
23
|
+
--_ta-th-bc: var(--bc-medium);
|
|
24
|
+
--_ta-th-fs: unset;
|
|
25
|
+
--_ta-th-p: var(--su8);
|
|
26
|
+
--_ta-th-ta: left;
|
|
27
|
+
--_ta-th-va: middle;
|
|
28
|
+
--_ta-th-w: unset;
|
|
29
|
+
|
|
30
|
+
// VARIANTS
|
|
31
|
+
&&__stripes {
|
|
32
|
+
--_ta-tbody-tr-even-bg: var(--black-025);
|
|
33
|
+
--_ta-thead-th-bg: var(--black-050);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// MODIFIERS
|
|
37
|
+
&.ta-center {
|
|
38
|
+
--_ta-td-ta: center;
|
|
39
|
+
--_ta-th-ta: center;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&.ta-left {
|
|
43
|
+
--_ta-td-ta: left;
|
|
44
|
+
--_ta-th-ta: left;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
&.ta-justify {
|
|
48
|
+
--_ta-td-ta: justify;
|
|
49
|
+
--_ta-th-ta: justify;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&.ta-right {
|
|
53
|
+
--_ta-td-ta: right;
|
|
54
|
+
--_ta-th-ta: right;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
&.va-bottom {
|
|
58
|
+
--_ta-td-va: bottom;
|
|
59
|
+
--_ta-th-va: bottom;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
&.va-middle {
|
|
63
|
+
--_ta-td-va: middle;
|
|
64
|
+
--_ta-th-va: middle;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&.va-top {
|
|
68
|
+
--_ta-td-va: top;
|
|
69
|
+
--_ta-th-va: top;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&&__b0 {
|
|
73
|
+
--_ta-td-bc: transparent;
|
|
74
|
+
--_ta-th-bc: transparent;
|
|
75
|
+
--_ta-tbody-tbody-bc: transparent; // [1]
|
|
76
|
+
--_ta-tbody-tbody-bw: var(--su-static12); // [1]
|
|
77
|
+
--_ta-thead-th-bg: transparent;
|
|
78
|
+
|
|
79
|
+
thead th {
|
|
80
|
+
font-size: inherit;
|
|
81
|
+
text-transform: initial;
|
|
82
|
+
letter-spacing: initial;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&&__bx {
|
|
87
|
+
tr {
|
|
88
|
+
> *:not(:first-child) {
|
|
89
|
+
border-left-color: transparent;
|
|
90
|
+
}
|
|
91
|
+
> *:not(:last-child) {
|
|
92
|
+
border-right-color: transparent;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
&&__bx-simple {
|
|
98
|
+
--_ta-thead-th-bg: transparent;
|
|
99
|
+
--_ta-foot-td-bc: transparent;
|
|
100
|
+
--_ta-foot-th-bc: transparent;
|
|
101
|
+
|
|
102
|
+
td,
|
|
103
|
+
th {
|
|
104
|
+
border-left-color: transparent;
|
|
105
|
+
border-right-color: transparent;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
tbody tr {
|
|
109
|
+
&:first-of-type th,
|
|
110
|
+
&:first-of-type td {
|
|
111
|
+
border-top-color: transparent;
|
|
112
|
+
}
|
|
113
|
+
&:last-of-type th,
|
|
114
|
+
&:last-of-type td {
|
|
115
|
+
border-bottom-color: transparent;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
thead th {
|
|
120
|
+
border-top-color: transparent;
|
|
121
|
+
border-bottom-color: var(--bc-darker);
|
|
122
|
+
font-size: inherit;
|
|
123
|
+
text-transform: initial;
|
|
124
|
+
letter-spacing: initial;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
&&__sortable {
|
|
129
|
+
thead th {
|
|
130
|
+
a { // If an anchor is used, it should appear like a normal header
|
|
131
|
+
color: inherit;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&.is-sorted { // Selected state
|
|
135
|
+
color: var(--black-900);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
color: var(--fc-light);
|
|
139
|
+
cursor: pointer;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Sizes
|
|
144
|
+
&&__sm {
|
|
145
|
+
--_ta-td-p: var(--su4);
|
|
146
|
+
--_ta-th-p: var(--su4);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
&&__lg {
|
|
150
|
+
--_ta-td-p: var(--su12);
|
|
151
|
+
--_ta-th-p: var(--su12);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// CHILD ELEMENTS
|
|
155
|
+
& &--cell {
|
|
156
|
+
.generate-cell-widths-classes(@n, @i: 1) when (@i =< @n) {
|
|
157
|
+
&@{i} { // generates iterated cell classes
|
|
158
|
+
@ta-cell-w: @ta-columns * @i;
|
|
159
|
+
--_ta-td-w: @ta-cell-w;
|
|
160
|
+
--_ta-th-w: @ta-cell-w;
|
|
161
|
+
}
|
|
162
|
+
.generate-cell-widths-classes(@n, (@i + 1));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
.generate-cell-widths-classes(12);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
& &--totals {
|
|
169
|
+
--_ta-td-fs: var(--fs-subheading);
|
|
170
|
+
--_ta-td-pt: var(--su12);
|
|
171
|
+
--_ta-td-fw: bold;
|
|
172
|
+
--_ta-th-fs: var(--fs-subheading);
|
|
173
|
+
--_ta-th-pt: var(--su12);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
tbody {
|
|
177
|
+
+ tbody { // If two table bodies are next to each other, visually separate them
|
|
178
|
+
border-top: var(--_ta-tbody-tbody-bw) solid var(--_ta-tbody-tbody-bc);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
th {
|
|
182
|
+
font-weight: normal;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
tr {
|
|
186
|
+
&:nth-child(2n) {
|
|
187
|
+
background-color: var(--_ta-tbody-tr-even-bg);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
td {
|
|
193
|
+
.s-checkbox {
|
|
194
|
+
display: block;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
&.s-table--bulk {
|
|
198
|
+
--_ta-td-w: calc(var(--su32) - var(--su2)); // 30px;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
&.s-table--progress {
|
|
202
|
+
--_ta-td-ta: right;
|
|
203
|
+
--_ta-td-brw: 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
&.s-table--progress-bar {
|
|
207
|
+
--_ta-td-blw: 0;
|
|
208
|
+
--_ta-td-pl: 0;
|
|
209
|
+
--_ta-td-w: 120px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
border: var(--su-static1) solid var(--_ta-td-bc);
|
|
213
|
+
border-bottom-width: var(--_ta-td-bbw, var(--su-static1));
|
|
214
|
+
border-left-width: var(--_ta-td-blw, var(--su-static1));
|
|
215
|
+
border-right-width: var(--_ta-td-brw, var(--su-static1));
|
|
216
|
+
border-top-width: var(--_ta-td-btw, var(--su-static1));
|
|
217
|
+
font-size: var(--_ta-td-fs);
|
|
218
|
+
font-weight: var(--_ta-td-fw);
|
|
219
|
+
padding: var(--_ta-td-p);
|
|
220
|
+
padding-left: var(--_ta-td-pl, var(--_ta-td-p));
|
|
221
|
+
padding-top: var(--_ta-td-pt, var(--_ta-td-p));
|
|
222
|
+
text-align: var(--_ta-td-ta);
|
|
223
|
+
vertical-align: var(--_ta-td-va);
|
|
224
|
+
width: var(--_ta-td-w);
|
|
225
|
+
|
|
226
|
+
color: var(--fc-medium);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
tfoot {
|
|
230
|
+
td {
|
|
231
|
+
border-bottom-color: var(--_ta-foot-td-bc, var(--_ta-td-bc));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
th {
|
|
235
|
+
border-bottom-color: var(--_ta-foot-th-bc, var(--_ta-td-bc));
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
th {
|
|
240
|
+
.s-checkbox {
|
|
241
|
+
display: block;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
&.s-table--bulk {
|
|
245
|
+
--_ta-th-w: calc(var(--su32) - var(--su2)); // 30px;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
border: var(--su-static1) solid var(--_ta-th-bc);
|
|
249
|
+
border-width: var(--su-static1) var(--su-static1) var(--_ta-th-bbw);
|
|
250
|
+
font-size: var(--_ta-th-fs);
|
|
251
|
+
padding: var(--_ta-th-p);
|
|
252
|
+
padding-top: var(--_ta-th-pt, var(--_ta-th-p));
|
|
253
|
+
text-align: var(--_ta-th-ta);
|
|
254
|
+
vertical-align: var(--_ta-th-va);
|
|
255
|
+
width: var(--_ta-th-w);
|
|
256
|
+
|
|
257
|
+
color: var(--fc-dark);
|
|
258
|
+
font-weight: bold;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
thead {
|
|
262
|
+
th {
|
|
263
|
+
background-color: var(--_ta-thead-th-bg);
|
|
264
|
+
|
|
265
|
+
line-height: var(--lh-sm);
|
|
266
|
+
vertical-align: bottom;
|
|
267
|
+
white-space: nowrap;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
tr {
|
|
272
|
+
&:last-of-type {
|
|
273
|
+
--_ta-td-bbw: var(--su-static1);
|
|
274
|
+
--_ta-th-bbw: var(--su-static1);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
&.is-disabled {
|
|
278
|
+
background-color: var(--black-025);
|
|
279
|
+
--_ta-tbody-tr-even-bg: var(--black-025);
|
|
280
|
+
|
|
281
|
+
th:not(.is-enabled),
|
|
282
|
+
td:not(.is-enabled) {
|
|
283
|
+
opacity: calc(var(--_o-disabled) * 0.6); // 0.5 * 0.6 = 0.3
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
border-collapse: collapse;
|
|
289
|
+
border-spacing: 0;
|
|
290
|
+
display: table;
|
|
291
|
+
font-size: var(--fs-body1);
|
|
292
|
+
max-width: 100%;
|
|
293
|
+
width: 100%;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// [1] This makes the border transparent, so we need to use whitespace
|
|
297
|
+
// to achieve the same effect a 2px gray border achieves.
|
|
@@ -17,14 +17,6 @@
|
|
|
17
17
|
// -- SET BASIC STYLES FOR BODY
|
|
18
18
|
@import "base/body.less";
|
|
19
19
|
|
|
20
|
-
// -- COMPONENTS
|
|
21
|
-
@import "components/buttons.less";
|
|
22
|
-
@import "components/links.less";
|
|
23
|
-
@import "components/link-previews.less";
|
|
24
|
-
@import "components/notices.less";
|
|
25
|
-
@import "components/tags.less";
|
|
26
|
-
@import "components/pagination.less";
|
|
27
|
-
|
|
28
20
|
// -- LESS CONSTANTS AND MIXINS
|
|
29
21
|
@import "exports/exports.less";
|
|
30
22
|
|
|
@@ -18,10 +18,13 @@
|
|
|
18
18
|
|
|
19
19
|
// -- COMPONENTS
|
|
20
20
|
@import "components/activity-indicator.less";
|
|
21
|
+
@import "components/anchors.less";
|
|
21
22
|
@import "components/award-bling.less";
|
|
22
23
|
@import "components/avatars.less";
|
|
23
24
|
@import "components/badges.less";
|
|
25
|
+
@import "components/buttons.less";
|
|
24
26
|
@import "components/empty-states.less";
|
|
27
|
+
@import "components/block-link.less";
|
|
25
28
|
@import "components/breadcrumbs.less";
|
|
26
29
|
@import "components/button-groups.less";
|
|
27
30
|
@import "components/cards.less";
|
|
@@ -29,17 +32,22 @@
|
|
|
29
32
|
@import "components/expandable.less";
|
|
30
33
|
@import "components/inputs.less";
|
|
31
34
|
@import "components/labels.less";
|
|
35
|
+
@import "components/link.less";
|
|
36
|
+
@import "components/link-previews.less";
|
|
32
37
|
@import "components/menu.less";
|
|
33
38
|
@import "components/modals.less";
|
|
34
39
|
@import "components/navigation.less";
|
|
40
|
+
@import "components/notices.less";
|
|
35
41
|
@import "components/page-titles.less";
|
|
42
|
+
@import "components/pagination.less";
|
|
36
43
|
@import "components/popovers.less";
|
|
37
44
|
@import "components/post-summary.less";
|
|
38
45
|
@import "components/progress-bars.less";
|
|
39
46
|
@import "components/prose.less";
|
|
40
47
|
@import "components/sidebar-widgets.less";
|
|
41
48
|
@import "components/spinner.less";
|
|
42
|
-
@import "components/
|
|
49
|
+
@import "components/table.less";
|
|
50
|
+
@import "components/tags.less";
|
|
43
51
|
@import "components/toggle-switches.less";
|
|
44
52
|
@import "components/topbar.less";
|
|
45
53
|
@import "components/uploader.less";
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { html, fixture, expect } from "@open-wc/testing";
|
|
2
|
+
import { screen } from "@testing-library/dom";
|
|
3
|
+
import "../ts/index";
|
|
4
|
+
|
|
5
|
+
// TODO abstract to a helper file… maybe create a helper function to test in all themes
|
|
6
|
+
const colorThemes = ["theme-dark", "theme-light"];
|
|
7
|
+
const baseThemes = ["", "theme-highcontrast"];
|
|
8
|
+
|
|
9
|
+
const avatarStyles = {
|
|
10
|
+
sizes: ["24", "32", "48", "64", "96", "128"],
|
|
11
|
+
children: ["image", "letter"],
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const makeTest = ({ testid, theme, classes, child = "" }) => {
|
|
15
|
+
it(`a11y: ${testid} styles in should be accessible`, async () => {
|
|
16
|
+
await fixture(html`<a
|
|
17
|
+
href="#"
|
|
18
|
+
class="s-avatar${classes}"
|
|
19
|
+
data-testid="${testid}"
|
|
20
|
+
>
|
|
21
|
+
<div
|
|
22
|
+
class="${child === "letter" ? "s-avatar--letter" : "d-none"}"
|
|
23
|
+
aria-hidden="true"
|
|
24
|
+
>
|
|
25
|
+
S
|
|
26
|
+
</div>
|
|
27
|
+
<img
|
|
28
|
+
class="${child === "image" ? "s-avatar--image" : "d-none"}"
|
|
29
|
+
src="https://picsum.photos/48"
|
|
30
|
+
alt="team logo"
|
|
31
|
+
/>
|
|
32
|
+
<span class="v-visible-sr">Stack Overflow</span>
|
|
33
|
+
</a>`);
|
|
34
|
+
|
|
35
|
+
document.body.className = "";
|
|
36
|
+
document.body.classList.add(...theme);
|
|
37
|
+
const avatar = screen.getByTestId(testid);
|
|
38
|
+
// TODO add conditional option for high contrast mode to test against AAA
|
|
39
|
+
await expect(avatar).to.be.accessible();
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
describe("s-avatar", () => {
|
|
44
|
+
// Test default, high contrast themes
|
|
45
|
+
baseThemes.forEach((baseTheme) => {
|
|
46
|
+
// Test light, dark theme
|
|
47
|
+
colorThemes.forEach((colorTheme) => {
|
|
48
|
+
const testidBase = `s-avatar-${
|
|
49
|
+
baseTheme ? `${baseTheme}-` : ""
|
|
50
|
+
}${colorTheme}`;
|
|
51
|
+
const theme = [baseTheme, colorTheme].filter(Boolean);
|
|
52
|
+
|
|
53
|
+
// Test each size
|
|
54
|
+
["", ...avatarStyles.sizes].forEach((size) => {
|
|
55
|
+
const sizeClasses = size ? ` s-avatar__${size}` : "";
|
|
56
|
+
const classesSize = ` ${sizeClasses}`;
|
|
57
|
+
const testidSize = `${testidBase}-${size}`;
|
|
58
|
+
|
|
59
|
+
// Test each size with each child
|
|
60
|
+
["", ...avatarStyles.children].forEach((child) => {
|
|
61
|
+
const testidChildren = `${testidSize}${
|
|
62
|
+
child ? `-with-${child}` : ""
|
|
63
|
+
}`;
|
|
64
|
+
makeTest({
|
|
65
|
+
child,
|
|
66
|
+
classes: classesSize,
|
|
67
|
+
testid: testidChildren,
|
|
68
|
+
theme,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { html, fixture, expect } from "@open-wc/testing";
|
|
2
|
+
import { screen } from "@testing-library/dom";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import "../ts/index";
|
|
5
|
+
import { showBanner, hideBanner } from "../ts/index";
|
|
6
|
+
|
|
7
|
+
const user = userEvent.setup();
|
|
8
|
+
|
|
9
|
+
describe("s-banner", () => {
|
|
10
|
+
it("trigger should make banner visible", async () => {
|
|
11
|
+
await fixture(html`
|
|
12
|
+
<button data-toggle="s-banner" data-target="#test-banner">
|
|
13
|
+
Show test banner
|
|
14
|
+
</button>
|
|
15
|
+
<aside
|
|
16
|
+
role="alert"
|
|
17
|
+
id="test-banner"
|
|
18
|
+
class="s-banner"
|
|
19
|
+
aria-labelledby="banner-message"
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
data-controller="s-banner"
|
|
22
|
+
data-s-banner-target="banner"
|
|
23
|
+
data-testid="test-banner"
|
|
24
|
+
>
|
|
25
|
+
Test banner
|
|
26
|
+
</aside>
|
|
27
|
+
`);
|
|
28
|
+
|
|
29
|
+
const button = screen.getByRole("button");
|
|
30
|
+
const banner = screen.getByTestId("test-banner");
|
|
31
|
+
|
|
32
|
+
expect(banner).to.have.attribute("aria-hidden", "true");
|
|
33
|
+
button.addEventListener("click", () => showBanner(banner));
|
|
34
|
+
|
|
35
|
+
await user.click(button);
|
|
36
|
+
expect(banner).to.have.attribute("aria-hidden", "false");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("trigger should hide banner", async () => {
|
|
40
|
+
await fixture(html`
|
|
41
|
+
<aside
|
|
42
|
+
role="alert"
|
|
43
|
+
id="test-banner"
|
|
44
|
+
class="s-banner"
|
|
45
|
+
aria-labelledby="banner-message"
|
|
46
|
+
aria-hidden="false"
|
|
47
|
+
data-controller="s-banner"
|
|
48
|
+
data-s-banner-target="banner"
|
|
49
|
+
data-testid="test-banner"
|
|
50
|
+
>
|
|
51
|
+
Test banner
|
|
52
|
+
<button
|
|
53
|
+
type="button"
|
|
54
|
+
class="s-btn s-banner--btn"
|
|
55
|
+
aria-label="Dismiss"
|
|
56
|
+
data-toggle="s-banner"
|
|
57
|
+
data-target="#test-banner"
|
|
58
|
+
>
|
|
59
|
+
Close banner
|
|
60
|
+
</button>
|
|
61
|
+
</aside>
|
|
62
|
+
`);
|
|
63
|
+
|
|
64
|
+
const button = screen.getByRole("button");
|
|
65
|
+
const banner = screen.getByTestId("test-banner");
|
|
66
|
+
|
|
67
|
+
expect(banner).to.have.attribute("aria-hidden", "false");
|
|
68
|
+
button.addEventListener("click", () => hideBanner(banner));
|
|
69
|
+
|
|
70
|
+
await user.click(button);
|
|
71
|
+
expect(banner).to.have.attribute("aria-hidden", "true");
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { html, fixture } from "@open-wc/testing";
|
|
2
|
+
import { visualDiff } from "@web/test-runner-visual-regression";
|
|
3
|
+
import "../ts/index";
|
|
4
|
+
|
|
5
|
+
const testBanner = (variant = "info", important = false) => {
|
|
6
|
+
const importantClass = important ? "s-banner__important" : "";
|
|
7
|
+
|
|
8
|
+
return html`<aside
|
|
9
|
+
class="s-banner s-banner__${variant} ${importantClass} is-pinned ps-relatives"
|
|
10
|
+
role="alert"
|
|
11
|
+
aria-hidden="false"
|
|
12
|
+
>
|
|
13
|
+
<div
|
|
14
|
+
class="d-flex flex__center jc-space-between s-banner--container"
|
|
15
|
+
role="alertdialog"
|
|
16
|
+
aria-describedby="banner-message"
|
|
17
|
+
>
|
|
18
|
+
<div aria-label="banner message">
|
|
19
|
+
Test Banner: ${variant} ${importantClass}
|
|
20
|
+
</div>
|
|
21
|
+
<div class="ml-auto myn8">
|
|
22
|
+
<span class="s-btn s-banner--btn">Close</span>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</aside>`;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
describe("s-banner", () => {
|
|
29
|
+
it("should not introduce visual regressions for info banner", async () => {
|
|
30
|
+
const banner = await fixture(testBanner("info"));
|
|
31
|
+
await visualDiff(banner, "s-banner__info");
|
|
32
|
+
});
|
|
33
|
+
it("should not introduce visual regressions for important info banner", async () => {
|
|
34
|
+
const banner = await fixture(testBanner("info", true));
|
|
35
|
+
await visualDiff(banner, "s-banner__info-important");
|
|
36
|
+
});
|
|
37
|
+
it("should not introduce visual regressions for success banner", async () => {
|
|
38
|
+
const banner = await fixture(testBanner("success"));
|
|
39
|
+
await visualDiff(banner, "s-banner__success");
|
|
40
|
+
});
|
|
41
|
+
it("should not introduce visual regressions for important success banner", async () => {
|
|
42
|
+
const banner = await fixture(testBanner("success", true));
|
|
43
|
+
await visualDiff(banner, "s-banner__success-important");
|
|
44
|
+
});
|
|
45
|
+
it("should not introduce visual regressions for warning banner", async () => {
|
|
46
|
+
const banner = await fixture(testBanner("warning"));
|
|
47
|
+
await visualDiff(banner, "s-banner__warning");
|
|
48
|
+
});
|
|
49
|
+
it("should not introduce visual regressions for important warning banner", async () => {
|
|
50
|
+
const banner = await fixture(testBanner("warning", true));
|
|
51
|
+
await visualDiff(banner, "s-banner__warning-important");
|
|
52
|
+
});
|
|
53
|
+
it("should not introduce visual regressions for danger banner", async () => {
|
|
54
|
+
const banner = await fixture(testBanner("danger"));
|
|
55
|
+
await visualDiff(banner, "s-banner__danger");
|
|
56
|
+
});
|
|
57
|
+
it("should not introduce visual regressions for important danger banner", async () => {
|
|
58
|
+
const banner = await fixture(testBanner("danger", true));
|
|
59
|
+
await visualDiff(banner, "s-banner__danger-important");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// import { html, fixture } from "@open-wc/testing";
|
|
2
|
+
// import { visualDiff } from "@web/test-runner-visual-regression";
|
|
3
|
+
// import "../ts/index";
|
|
4
|
+
|
|
5
|
+
// describe("s-btn", () => {
|
|
6
|
+
// it("should not introduce visual regressions for loading button", async () => {
|
|
7
|
+
// const btn = await fixture(html`
|
|
8
|
+
// <button class="s-btn is-loading" type="button">Loading</button>
|
|
9
|
+
// `);
|
|
10
|
+
// await visualDiff(btn, "s-btn-is-loading");
|
|
11
|
+
// });
|
|
12
|
+
// });
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { html, fixture, expect } from "@open-wc/testing";
|
|
2
|
+
import { screen } from "@testing-library/dom";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import "../ts/index";
|
|
5
|
+
import { showToast, hideToast } from "../ts/index";
|
|
6
|
+
|
|
7
|
+
const user = userEvent.setup();
|
|
8
|
+
|
|
9
|
+
const testToast = (hidden = true) => html` <button
|
|
10
|
+
class="js-open-test-toast"
|
|
11
|
+
data-toggle="s-toast"
|
|
12
|
+
data-target="#test-toast"
|
|
13
|
+
>
|
|
14
|
+
Show test toast
|
|
15
|
+
</button>
|
|
16
|
+
<button type="button" aria-label="Dismiss">Close toast</button>
|
|
17
|
+
<div
|
|
18
|
+
role="alertdialog"
|
|
19
|
+
id="test-toast"
|
|
20
|
+
class="s-toast"
|
|
21
|
+
aria-hidden="${hidden}"
|
|
22
|
+
aria-labelledby="toast-message"
|
|
23
|
+
data-controller="s-toast"
|
|
24
|
+
data-s-toast-target="toast"
|
|
25
|
+
data-s-toast-return-element=".js-open-test-toast[data-target='#test-toast']"
|
|
26
|
+
data-testid="test-toast"
|
|
27
|
+
>
|
|
28
|
+
<aside class="s-notice s-notice__success">
|
|
29
|
+
<div id="notice-message">Test toast</div>
|
|
30
|
+
</aside>
|
|
31
|
+
</div>`;
|
|
32
|
+
|
|
33
|
+
describe("s-toast", () => {
|
|
34
|
+
it("trigger should make toast visible", async () => {
|
|
35
|
+
await fixture(testToast(true));
|
|
36
|
+
|
|
37
|
+
const button = screen.getAllByRole("button")[0]; // Trigger button
|
|
38
|
+
const toast = screen.getByTestId("test-toast");
|
|
39
|
+
|
|
40
|
+
expect(toast).to.have.attribute("aria-hidden", "true");
|
|
41
|
+
button.addEventListener("click", () => showToast(toast));
|
|
42
|
+
|
|
43
|
+
await user.click(button);
|
|
44
|
+
expect(toast).to.have.attribute("aria-hidden", "false");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("trigger should hide toast", async () => {
|
|
48
|
+
await fixture(testToast(false));
|
|
49
|
+
|
|
50
|
+
const button = screen.getAllByRole("button")[1]; // Close button
|
|
51
|
+
const toast = screen.getByTestId("test-toast");
|
|
52
|
+
|
|
53
|
+
expect(toast).to.have.attribute("aria-hidden", "false");
|
|
54
|
+
button.addEventListener("click", () => hideToast(toast));
|
|
55
|
+
|
|
56
|
+
await user.click(button);
|
|
57
|
+
expect(toast).to.have.attribute("aria-hidden", "true");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// TODO: add test for refocus trigger
|
|
61
|
+
|
|
62
|
+
// TODO: add test for removing toast from DOM
|
|
63
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { html, fixture } from "@open-wc/testing";
|
|
2
|
+
import { visualDiff } from "@web/test-runner-visual-regression";
|
|
3
|
+
import "../ts/index";
|
|
4
|
+
|
|
5
|
+
const testToast = (variant = "info", important = false) => {
|
|
6
|
+
const importantClass = important ? "s-notice__important" : "";
|
|
7
|
+
|
|
8
|
+
return html`<div class="s-toast" aria-hidden="false">
|
|
9
|
+
<aside class="s-notice s-notice__${variant} ${importantClass}">
|
|
10
|
+
Test toast: ${variant} ${importantClass}
|
|
11
|
+
</aside>
|
|
12
|
+
</div>`;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
describe("s-toast", () => {
|
|
16
|
+
it("should not introduce visual regressions for info toast", async () => {
|
|
17
|
+
const toast = await fixture(testToast("info"));
|
|
18
|
+
await visualDiff(toast, "s-toast__info");
|
|
19
|
+
});
|
|
20
|
+
it("should not introduce visual regressions for important info toast", async () => {
|
|
21
|
+
const toast = await fixture(testToast("info", true));
|
|
22
|
+
await visualDiff(toast, "s-toast__info-important");
|
|
23
|
+
});
|
|
24
|
+
it("should not introduce visual regressions for success toast", async () => {
|
|
25
|
+
const toast = await fixture(testToast("success"));
|
|
26
|
+
await visualDiff(toast, "s-toast__success");
|
|
27
|
+
});
|
|
28
|
+
it("should not introduce visual regressions for important success toast", async () => {
|
|
29
|
+
const toast = await fixture(testToast("success", true));
|
|
30
|
+
await visualDiff(toast, "s-toast__success-important");
|
|
31
|
+
});
|
|
32
|
+
it("should not introduce visual regressions for warning toast", async () => {
|
|
33
|
+
const toast = await fixture(testToast("warning"));
|
|
34
|
+
await visualDiff(toast, "s-toast__warning");
|
|
35
|
+
});
|
|
36
|
+
it("should not introduce visual regressions for important warning toast", async () => {
|
|
37
|
+
const toast = await fixture(testToast("warning", true));
|
|
38
|
+
await visualDiff(toast, "s-toast__warning-important");
|
|
39
|
+
});
|
|
40
|
+
it("should not introduce visual regressions for danger toast", async () => {
|
|
41
|
+
const toast = await fixture(testToast("danger"));
|
|
42
|
+
await visualDiff(toast, "s-toast__danger");
|
|
43
|
+
});
|
|
44
|
+
it("should not introduce visual regressions for important danger toast", async () => {
|
|
45
|
+
const toast = await fixture(testToast("danger", true));
|
|
46
|
+
await visualDiff(toast, "s-toast__danger-important");
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// export all controllers *with helpers* so they can be bulk re-exported by the package entry point
|
|
2
2
|
export { ExpandableController } from "./s-expandable-control";
|
|
3
3
|
export { hideModal, ModalController, showModal } from "./s-modal";
|
|
4
|
+
export { hideBanner, BannerController, showBanner } from "./s-banner";
|
|
5
|
+
export { hideToast, ToastController, showToast } from "./s-toast";
|
|
4
6
|
export { TabListController } from "./s-navigation-tablist";
|
|
5
7
|
export {
|
|
6
8
|
attachPopover,
|