@stackoverflow/stacks 1.7.0 → 1.8.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/README.md +1 -1
- package/dist/css/stacks.css +677 -508
- package/dist/css/stacks.min.css +1 -1
- package/lib/css/base/fieldset.less +5 -0
- package/lib/css/components/buttons.less +4 -4
- package/lib/css/components/checkboxes-radios.less +158 -0
- package/lib/css/components/description.less +9 -0
- package/lib/css/components/inputs.less +198 -567
- package/lib/css/components/labels.less +4 -4
- package/lib/css/components/link.less +23 -8
- package/lib/css/components/post-summary.less +10 -2
- package/lib/css/components/select.less +148 -0
- package/lib/css/components/tags.less +3 -3
- package/lib/css/components/toggle-switches.less +8 -0
- package/lib/css/exports/mixins.less +73 -11
- package/lib/css/input-utils.less +44 -0
- package/lib/css/stacks-static.less +16 -26
- package/lib/test/s-avatar.a11y.test.ts +77 -0
- package/lib/test/s-btn.a11y.test.ts +123 -0
- package/lib/test/{s-button.visual.test.ts → s-btn.visual.test.ts} +5 -1
- package/package.json +17 -16
|
@@ -23,19 +23,19 @@
|
|
|
23
23
|
// MODIFIERS
|
|
24
24
|
// Sizes
|
|
25
25
|
&&__sm {
|
|
26
|
-
|
|
26
|
+
.size-styles(sm; la; @styles: fs);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
&&__md {
|
|
30
|
-
|
|
30
|
+
.size-styles(md; la; @styles: fs);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
&&__lg {
|
|
34
|
-
|
|
34
|
+
.size-styles(lg; la; @styles: fs);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
&&__xl {
|
|
38
|
-
|
|
38
|
+
.size-styles(xl; la; @styles: fs);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// CHILD ELEMENTS
|
|
@@ -13,6 +13,21 @@ a,
|
|
|
13
13
|
|
|
14
14
|
// STATES
|
|
15
15
|
&.s-link {
|
|
16
|
+
&__danger,
|
|
17
|
+
&__grayscale,
|
|
18
|
+
&__inherit,
|
|
19
|
+
&__muted,
|
|
20
|
+
&__visited {
|
|
21
|
+
&:visited {
|
|
22
|
+
&:active,
|
|
23
|
+
&:hover {
|
|
24
|
+
color: var(--_li-fc-hover);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
color: var(--_li-fc-visited);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
// MODIFIERS
|
|
17
32
|
&__dropdown {
|
|
18
33
|
&:after {
|
|
@@ -68,17 +83,17 @@ a,
|
|
|
68
83
|
}
|
|
69
84
|
}
|
|
70
85
|
|
|
86
|
+
// MODIFIERS
|
|
87
|
+
fieldset[disabled] & {
|
|
88
|
+
box-shadow: none !important;
|
|
89
|
+
opacity: var(--_o-disabled-static);
|
|
90
|
+
pointer-events: none;
|
|
91
|
+
}
|
|
92
|
+
|
|
71
93
|
// INTERACTION
|
|
72
94
|
&:active,
|
|
73
95
|
&:hover {
|
|
74
|
-
|
|
75
|
-
&:visited {
|
|
76
|
-
color: var(--_li-fc-hover);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
&:visited {
|
|
81
|
-
color: var(--_li-fc-visited);
|
|
96
|
+
color: var(--_li-fc-hover);
|
|
82
97
|
}
|
|
83
98
|
|
|
84
99
|
color: var(--_li-fc);
|
|
@@ -206,8 +206,12 @@
|
|
|
206
206
|
margin: 0 !important;
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
&,
|
|
210
|
+
&.s-btn { // To override .s-btn class attributes
|
|
211
|
+
padding: var(--su8);
|
|
212
|
+
position: absolute;
|
|
213
|
+
}
|
|
214
|
+
|
|
211
215
|
right: var(--su8);
|
|
212
216
|
top: var(--su8);
|
|
213
217
|
}
|
|
@@ -295,6 +299,10 @@
|
|
|
295
299
|
|
|
296
300
|
&--stats-item {
|
|
297
301
|
&:not(.s-badge) {
|
|
302
|
+
&.is-deleted {
|
|
303
|
+
color: var(--white);
|
|
304
|
+
}
|
|
305
|
+
|
|
298
306
|
align-items: center;
|
|
299
307
|
border: var(--su1) solid transparent;
|
|
300
308
|
display: inline-flex;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
.s-select {
|
|
2
|
+
--_se-arrow-bc: currentColor transparent;
|
|
3
|
+
--_se-arrow-size: var(--su-static4); // Constant
|
|
4
|
+
--_se-select-bc: var(--bc-darker);
|
|
5
|
+
--_se-select-bc-focus: var(--theme-secondary-300);
|
|
6
|
+
--_se-select-bs-focus: 0 0 0 var(--su-static4) var(--focus-ring);
|
|
7
|
+
--_se-select-bg: var(--white);
|
|
8
|
+
--_se-select-br: var(--br-sm);
|
|
9
|
+
--_se-select-fc: var(--black);
|
|
10
|
+
--_se-select-px: 0.7em;
|
|
11
|
+
--_se-select-py: 0.6em;
|
|
12
|
+
--_se-select-fs: var(--fs-body1);
|
|
13
|
+
|
|
14
|
+
// CONTEXTUAL STYLES
|
|
15
|
+
@supports (-webkit-overflow-scrolling: touch) {
|
|
16
|
+
--_se-select-fs: 16px; // Increase font size for mobile safari. This keeps our inputs from zooming the page while focused
|
|
17
|
+
--_se-select-px: 0.55em; // Compensate for the larger font size so we generally keep the input the same size
|
|
18
|
+
--_se-select-py: 0.4em; // Compensate for the larger font size so we generally keep the input the same size
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// MODIFIERS
|
|
22
|
+
.input-states({
|
|
23
|
+
position: relative;
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
.validation-states(se-select);
|
|
27
|
+
|
|
28
|
+
.is-disabled & {
|
|
29
|
+
--_se-arrow-bc: var(--bc-darker) transparent;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&&__sm {
|
|
33
|
+
.size-styles(sm; se-select; @styles: fs);
|
|
34
|
+
// --_se-select-fs: var(--fs-caption);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&&__md {
|
|
38
|
+
.size-styles(md; se-select; @styles: br, fs);
|
|
39
|
+
--_se-select-py: 0.5em;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&&__lg {
|
|
43
|
+
.size-styles(lg; se-select; @styles: br, fs);
|
|
44
|
+
--_se-select-px: 0.6em;
|
|
45
|
+
--_se-select-py: 0.45em;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&&__xl {
|
|
49
|
+
.size-styles(xl; se-select; @styles: br, fs);
|
|
50
|
+
--_se-select-px: 0.5em;
|
|
51
|
+
--_se-select-py: 0.4em;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// CHILD ELEMENTS
|
|
55
|
+
select&,
|
|
56
|
+
& > select {
|
|
57
|
+
.webkit-autofill();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
&:before,
|
|
61
|
+
&:after { // menu arrows
|
|
62
|
+
border-color: var(--_se-arrow-bc);
|
|
63
|
+
border-style: solid;
|
|
64
|
+
border-width: var(--_se-arrow-size);
|
|
65
|
+
content: "";
|
|
66
|
+
pointer-events: none;
|
|
67
|
+
position: absolute;
|
|
68
|
+
right: calc(var(--su-static12) + var(--su-static1));
|
|
69
|
+
z-index: var(--zi-selected);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&:after {
|
|
73
|
+
border-bottom-width: 0;
|
|
74
|
+
top: calc(50% + var(--su-static1));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&:before {
|
|
78
|
+
border-top-width: 0;
|
|
79
|
+
top: calc(50% - calc(var(--_se-arrow-size) + var(--su-static1)));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
> select { // Menu
|
|
83
|
+
// CONTEXTUAL STYLES
|
|
84
|
+
fieldset[disabled] &,
|
|
85
|
+
&[disabled] {
|
|
86
|
+
cursor: not-allowed;
|
|
87
|
+
opacity: var(--_o-disabled-static);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
&[readonly],
|
|
91
|
+
.is-readonly & { // [1]
|
|
92
|
+
--_se-select-bc: var(--bc-light);
|
|
93
|
+
--_se-select-bg: var(--black-050);
|
|
94
|
+
--_se-select-fc: var(--black-200);
|
|
95
|
+
|
|
96
|
+
.highcontrast-mode({
|
|
97
|
+
--_se-select-fc: var(--fc-light);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
cursor: not-allowed;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// CHILD ELEMENTS
|
|
104
|
+
&::-moz-focus-inner {
|
|
105
|
+
outline: none !important;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// INTERACTION
|
|
109
|
+
&:focus {
|
|
110
|
+
.highcontrast-mode({
|
|
111
|
+
--_se-select-bc-focus: var(--black);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
border-color: var(--_se-select-bc-focus);
|
|
115
|
+
box-shadow: var(--_se-select-bs-focus);
|
|
116
|
+
|
|
117
|
+
color: var(--black);
|
|
118
|
+
outline: 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
background-color: var(--_se-select-bg);
|
|
122
|
+
border: var(--su-static1) solid var(--_se-select-bc);
|
|
123
|
+
border-radius: var(--_se-select-br);
|
|
124
|
+
color: var(--_se-select-fc);
|
|
125
|
+
font-size: var(--_se-select-fs);
|
|
126
|
+
padding: var(--_se-select-py) var(--_se-select-px);
|
|
127
|
+
|
|
128
|
+
appearance: none;
|
|
129
|
+
font-family: inherit;
|
|
130
|
+
height: 100%; // Fill the height of its parent
|
|
131
|
+
line-height: var(--lh-sm);
|
|
132
|
+
outline: 0;
|
|
133
|
+
padding-right: var(--su32);
|
|
134
|
+
position: relative; // This prevents Firefox from requiring a second click to select options
|
|
135
|
+
width: 100%;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.s-input-icon {
|
|
139
|
+
right: var(--su32);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
color: var(--fc-dark);
|
|
143
|
+
position: relative;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// [1] The readonly attribute is not supported on select elements
|
|
147
|
+
// See https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly
|
|
148
|
+
// and https://github.com/StackExchange/Stacks/pull/1040#discussion_r931144086
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
// MODIFIERS
|
|
43
43
|
// Sizes
|
|
44
44
|
&&__xs {
|
|
45
|
-
|
|
45
|
+
.size-styles(xs; ta; @styles: fs);
|
|
46
46
|
--_ta-lh: 1.4;
|
|
47
47
|
--_ta-px: var(--su2);
|
|
48
48
|
}
|
|
49
49
|
&&__sm {
|
|
50
|
-
|
|
50
|
+
.size-styles(sm; ta; @styles: fs);
|
|
51
51
|
--_ta-lh: 1.5;
|
|
52
52
|
}
|
|
53
53
|
&&__md {
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
--_ta-lh: 1.733333333;
|
|
57
57
|
}
|
|
58
58
|
&&__lg {
|
|
59
|
-
--_ta-br: calc(var(--br-sm) +
|
|
59
|
+
--_ta-br: calc(var(--br-sm) + var(--su-static1));
|
|
60
60
|
--_ta-fs: var(--fs-subheading);
|
|
61
61
|
--_ta-lh: 1.684210526;
|
|
62
62
|
--_ta-px: var(--su6);
|
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
--_ts-multiple-bg: unset;
|
|
6
6
|
--_ts-multiple-fc: var(--black-500);
|
|
7
7
|
|
|
8
|
+
fieldset[disabled] & {
|
|
9
|
+
&,
|
|
10
|
+
& label {
|
|
11
|
+
cursor: not-allowed;
|
|
12
|
+
opacity: var(--_o-disabled-static);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
&&__multiple { // TODO split single and multiple toggle into two seperate components
|
|
9
17
|
input[type="radio"] {
|
|
10
18
|
&:checked {
|
|
@@ -88,17 +88,6 @@
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
// ===========================================================================
|
|
92
|
-
// -- APPEARANCE
|
|
93
|
-
// Use this to overwrite the default appearance properties
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
|
-
.appearance(@all) {
|
|
96
|
-
-webkit-appearance: @all;
|
|
97
|
-
-moz-appearance: @all;
|
|
98
|
-
appearance: @all;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
91
|
// ===========================================================================
|
|
103
92
|
// -- FONT FACE
|
|
104
93
|
// Used to load hosted, custom webfonts. You must provide the font's
|
|
@@ -194,6 +183,79 @@
|
|
|
194
183
|
@amountDecimal);
|
|
195
184
|
}
|
|
196
185
|
|
|
186
|
+
// =============================================================================
|
|
187
|
+
// -- SIZE STYLES
|
|
188
|
+
// The following mixins let us generate pseudo-private custom properties
|
|
189
|
+
// for common sizes. They expect a size (@size), a prefix for the custom
|
|
190
|
+
// property (@prefix), and an array of comma-separates abbreviated styles
|
|
191
|
+
// (@styles).
|
|
192
|
+
// -----------------------------------------------------------------------------
|
|
193
|
+
|
|
194
|
+
.size-styles(@size, @prefix, @styles, @index: length(@styles)) {
|
|
195
|
+
& when (@index > 0) {
|
|
196
|
+
@style: extract(@styles, @index);
|
|
197
|
+
|
|
198
|
+
// xs
|
|
199
|
+
& when (@size = xs) and (@style = fs) {
|
|
200
|
+
--_@{prefix}-fs: var(--fs-fine);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// sm
|
|
204
|
+
& when (@size = sm) and (@style = fs) {
|
|
205
|
+
--_@{prefix}-fs: var(--fs-caption);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// md
|
|
209
|
+
& when (@size = md) and (@style = br) {
|
|
210
|
+
--_@{prefix}-br: calc(var(--br-sm) + var(--su-static1));
|
|
211
|
+
}
|
|
212
|
+
& when (@size = md) and (@style = fs) {
|
|
213
|
+
--_@{prefix}-fs: var(--fs-body3);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// lg
|
|
217
|
+
& when (@size = lg) and (@style = br) {
|
|
218
|
+
--_@{prefix}-br: calc(var(--br-sm) + var(--su-static1));
|
|
219
|
+
}
|
|
220
|
+
& when (@size = lg) and (@style = fs) {
|
|
221
|
+
--_@{prefix}-fs: var(--fs-title);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// xl
|
|
225
|
+
& when (@size = xl) and (@style = br) {
|
|
226
|
+
--_@{prefix}-br: var(--br-md);
|
|
227
|
+
}
|
|
228
|
+
& when (@size = xl) and (@style = fs) {
|
|
229
|
+
--_@{prefix}-fs: var(--fs-headline1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.size-styles(@size, @prefix, @styles, @index: @index - 1);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// =============================================================================
|
|
237
|
+
// -- WEBKIT AUTOFILL
|
|
238
|
+
// -----------------------------------------------------------------------------
|
|
239
|
+
.webkit-autofill() {
|
|
240
|
+
&:-webkit-autofill {
|
|
241
|
+
&:focus {
|
|
242
|
+
border-color: var(--blue-300);
|
|
243
|
+
// Since the box shadow is overwritten to show a background, we have to re-add the focus outline
|
|
244
|
+
-webkit-box-shadow: 0 0 0 1000px var(--blue-050) inset, 0 0 0 var(--su-static4) var(--focus-ring);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
-webkit-box-shadow: 0 0 0 1000px var(--theme-secondary-050) inset; // This acts as a background color by stretching an inset box shadow across the input
|
|
248
|
+
-webkit-text-fill-color: var(--black);
|
|
249
|
+
border-color: var(--blue-300);
|
|
250
|
+
transition: background-color 0s 50000s; // A hack to infinitely delay background styles that come from the browser.
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
&::-webkit-contacts-auto-fill-button {
|
|
254
|
+
background-color: var(--black); // In Safari, make the autocomplete button darkmode-aware
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
}
|
|
258
|
+
|
|
197
259
|
// ===========================================================================
|
|
198
260
|
// Internals only beyond this point -- helpers for .font-face()
|
|
199
261
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
.input-states(@rules) {
|
|
2
|
+
.is-disabled &,
|
|
3
|
+
.is-readonly &,
|
|
4
|
+
.has-success &,
|
|
5
|
+
.has-error &,
|
|
6
|
+
.has-warning & {
|
|
7
|
+
@rules();
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
.validation-states(@prefix, @error: {}, @success: {}, @warning: {}) {
|
|
12
|
+
.has-error &,
|
|
13
|
+
.has-success &,
|
|
14
|
+
.has-warning & {
|
|
15
|
+
--_@{prefix}-bc-focus: ~"var(--_@{prefix}-bc)";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.has-error & {
|
|
19
|
+
--_@{prefix}-bc: var(--red-400);
|
|
20
|
+
--_@{prefix}-bs-focus: 0 0 0 var(--su-static4) var(--focus-ring-error);
|
|
21
|
+
@error();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.has-success & {
|
|
25
|
+
--_@{prefix}-bc: var(--green-400);
|
|
26
|
+
--_@{prefix}-bs-focus: 0 0 0 var(--su-static4) var(--focus-ring-success);
|
|
27
|
+
@success();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.has-warning & {
|
|
31
|
+
--_@{prefix}-bc: var(--yellow-600);
|
|
32
|
+
--_@{prefix}-bs-focus: 0 0 0 var(--su-static4) var(--focus-ring-warning);
|
|
33
|
+
@warning();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.is-disabled,
|
|
38
|
+
.is-readonly,
|
|
39
|
+
.has-success,
|
|
40
|
+
.has-error,
|
|
41
|
+
.has-warning {
|
|
42
|
+
position: relative;
|
|
43
|
+
}
|
|
44
|
+
|
|
@@ -1,22 +1,11 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// STATIC STACK ELEMENTS
|
|
4
|
-
//
|
|
5
|
-
// This CSS comes from Stacks, our CSS & Pattern library for rapidly building
|
|
6
|
-
// Stack Overflow. For documentation of all these classes and how to contribute,
|
|
7
|
-
// visit https://stackoverflow.design/
|
|
8
|
-
//
|
|
9
|
-
// This is where all the magic happens.
|
|
10
|
-
//
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// $ STATIC ELEMENTS
|
|
13
|
-
// The following items are elements which we DO NOT allow communities
|
|
14
|
-
// to modify via variables.
|
|
15
|
-
// ----------------------------------------------------------------------------
|
|
1
|
+
// stacks-static.less contains styles which we DO NOT allow communities to modify via variables
|
|
2
|
+
// BASE
|
|
16
3
|
@import "base/reset.less";
|
|
4
|
+
@import "base/fieldset.less";
|
|
17
5
|
@import "base/icons.less";
|
|
6
|
+
@import "input-utils.less";
|
|
18
7
|
|
|
19
|
-
//
|
|
8
|
+
// COMPONENTS
|
|
20
9
|
@import "components/activity-indicator.less";
|
|
21
10
|
@import "components/anchors.less";
|
|
22
11
|
@import "components/award-bling.less";
|
|
@@ -28,7 +17,9 @@
|
|
|
28
17
|
@import "components/breadcrumbs.less";
|
|
29
18
|
@import "components/button-groups.less";
|
|
30
19
|
@import "components/cards.less";
|
|
20
|
+
@import "components/checkboxes-radios.less";
|
|
31
21
|
@import "components/code-blocks.less";
|
|
22
|
+
@import "components/description.less";
|
|
32
23
|
@import "components/expandable.less";
|
|
33
24
|
@import "components/inputs.less";
|
|
34
25
|
@import "components/labels.less";
|
|
@@ -44,6 +35,7 @@
|
|
|
44
35
|
@import "components/post-summary.less";
|
|
45
36
|
@import "components/progress-bars.less";
|
|
46
37
|
@import "components/prose.less";
|
|
38
|
+
@import "components/select.less";
|
|
47
39
|
@import "components/sidebar-widgets.less";
|
|
48
40
|
@import "components/spinner.less";
|
|
49
41
|
@import "components/table.less";
|
|
@@ -53,10 +45,10 @@
|
|
|
53
45
|
@import "components/uploader.less";
|
|
54
46
|
@import "components/user-cards.less";
|
|
55
47
|
|
|
56
|
-
//
|
|
48
|
+
// LESS CONSTANTS AND MIXINS
|
|
57
49
|
@import "exports/exports.less";
|
|
58
50
|
|
|
59
|
-
//
|
|
51
|
+
// ATOMIC CLASSES
|
|
60
52
|
@import "atomic/borders.less";
|
|
61
53
|
@import "atomic/colors.less";
|
|
62
54
|
@import "atomic/flex.less";
|
|
@@ -78,20 +70,18 @@
|
|
|
78
70
|
#stacks-internals-collect-small();
|
|
79
71
|
});
|
|
80
72
|
|
|
81
|
-
// We need printing styles to be last so they can override all other styles.
|
|
82
|
-
.print\:d-block {
|
|
83
|
-
@media print {
|
|
73
|
+
@media print { // We need printing styles to be last so they can override all other styles.
|
|
74
|
+
.print\:d-block & {
|
|
84
75
|
display: block !important;
|
|
85
76
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.print\:d-none {
|
|
89
|
-
@media print {
|
|
77
|
+
.print\:d-none & {
|
|
90
78
|
display: none !important;
|
|
91
79
|
}
|
|
92
80
|
}
|
|
93
81
|
/* stylelint-enable */
|
|
94
82
|
|
|
95
|
-
//
|
|
83
|
+
// CONFIG
|
|
96
84
|
@import "base/configuration-static.less";
|
|
97
85
|
@import "base/internals.less";
|
|
86
|
+
|
|
87
|
+
// [1] The following items are elements which we DO NOT allow communities to modify via variables.
|
|
@@ -0,0 +1,77 @@
|
|
|
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} 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
|
+
// TODO move to test utils
|
|
44
|
+
const buildTestid = (arr) => arr.filter(Boolean).join("-");
|
|
45
|
+
|
|
46
|
+
describe("s-avatar", () => {
|
|
47
|
+
// Test default, high contrast themes
|
|
48
|
+
baseThemes.forEach((baseTheme) => {
|
|
49
|
+
// Test light, dark theme
|
|
50
|
+
colorThemes.forEach((colorTheme) => {
|
|
51
|
+
const theme = [baseTheme, colorTheme].filter(Boolean);
|
|
52
|
+
const testidBase = buildTestid(["s-avatar", ...theme]);
|
|
53
|
+
|
|
54
|
+
// Test each size
|
|
55
|
+
["", ...avatarStyles.sizes].forEach((size) => {
|
|
56
|
+
const sizeClasses = size ? ` s-avatar__${size}` : "";
|
|
57
|
+
const classesSize = ` ${sizeClasses}`;
|
|
58
|
+
const testidSize = buildTestid([testidBase, size]);
|
|
59
|
+
|
|
60
|
+
// Test each size with each child
|
|
61
|
+
["", ...avatarStyles.children].forEach((child) => {
|
|
62
|
+
const testidChildren = buildTestid([
|
|
63
|
+
testidSize,
|
|
64
|
+
`with-${child}`,
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
makeTest({
|
|
68
|
+
child,
|
|
69
|
+
classes: classesSize,
|
|
70
|
+
testid: testidChildren,
|
|
71
|
+
theme,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|