@stackoverflow/stacks 2.5.6 → 2.5.8

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.
@@ -1,257 +1,257 @@
1
- .s-sidebarwidget {
2
- // COMPONENT-SPECIFIC CONSTANTS
3
- @sw-content-px: calc(var(--su16) - var(--su1)); // subtract 1px for border
4
- @sw-content-spacing-inner: var(--su12); // the spacing between two adjacent simple items
5
- @sw-content-spacing-outer: var(--su16); // the spacing at the start/end of a group of simple items, as well as between a complex item and its separator line
6
- // COMPONENT-SPECIFIC CUSTOM PROPERTIES
7
- --_sw-bc: var(--bc-medium);
8
- --_sw-after-bc: var(--_sw-bc);
9
- --_sw-content-bc: var(--bc-light);
10
- --_sw-header-bc: var(--_sw-content-bc);
11
-
12
- // MODIFIERS
13
- &:not(.s-anchors) {
14
- a:not(.button):not(.post-tag):not(.s-btn):not(.s-sidebarwidget--action):not(.s-user-card--link) {
15
- &,
16
- &:visited {
17
- color: var(--black-400);
18
- }
19
- }
20
- }
21
-
22
- // VARIANTS
23
- .alternate-color(blue);
24
- .alternate-color(yellow);
25
- .alternate-color(green);
26
-
27
- // CHILD ELEMENTS
28
- & &--action {
29
- color: var(--blue-400);
30
- float: right;
31
- font-size: var(--fs-fine);
32
- line-height: calc(var(--fs-body1) * 1.5); // 19.5px - line-height should be the same as in the outside element, so the header and action baselines line up
33
- margin: 0 0 var(--su4) var(--su8);
34
- }
35
-
36
- & &--content {
37
- &:not(table) {
38
- &:not(.s-sidebarwidget__items),
39
- &:not(.s-sidebarwidget__block-items) .s-sidebarwidget--item {
40
- display: flex;
41
- }
42
- }
43
-
44
- &.s-sidebarwidget__items {
45
- &,
46
- &.s-sidebarwidget__block-items .s-sidebarwidget--item {
47
- display: block;
48
- }
49
-
50
- padding: calc(@sw-content-spacing-outer - @sw-content-spacing-inner) @sw-content-px; // the items themselves provide part of the spacing, so the content padding needs to account for that
51
- }
52
-
53
- &:active {
54
- outline: none;
55
- }
56
-
57
- border-top: var(--su-static1) solid var(--_sw-content-bc);
58
- margin: 0;
59
- padding: @sw-content-spacing-outer @sw-content-px;
60
- }
61
-
62
- & &--header {
63
- &:first-child {
64
- border-top-left-radius: var(--br-sm);
65
- border-top-right-radius: var(--br-sm);
66
- }
67
-
68
- &.s-sidebarwidget {
69
- &__expanding-control {
70
- &:before {
71
- border: calc(var(--su-static4) + var(--su-static1)) solid transparent;
72
- border-left-color: var(--black-400);
73
- border-right-width: 0;
74
- content: '';
75
- float: left;
76
- margin-right: var(--su12);
77
- margin-top: calc(calc(var(--lh-base) * 1em) / 2 - 5px); // 1.3 is our standard line height
78
- transition: transform 0.3s cubic-bezier(0.4, 0.4, 0.6, 1);
79
- }
80
-
81
- &[aria-expanded='true']:before {
82
- transform: rotate(90deg);
83
- }
84
-
85
- cursor: pointer;
86
- }
87
-
88
- &__small-bold-text {
89
- .s-sidebarwidget--action {
90
- font-weight: normal;
91
- line-height: calc(var(--lh-base) * var(--fs-caption)); // line-height should be the same as in the outside element, so the header and action baselines line up
92
- }
93
-
94
- font-size: var(--fs-caption);
95
- font-weight: bold;
96
- }
97
- }
98
-
99
- &:active {
100
- outline: none;
101
- }
102
-
103
- background: var(--black-100);
104
- border-top: var(--su-static1) solid var(--_sw-header-bc);
105
- color: var(--black-500);
106
- font-size: var(--fs-body2);
107
- font-weight: normal;
108
- margin: 0;
109
- padding: @sw-content-spacing-inner @sw-content-px;
110
- }
111
-
112
- & &--item {
113
- &,
114
- & > :first-child {
115
- &[aria-current="true"],
116
- &[aria-current="page"] {
117
- &:before {
118
- border-left-color: var(--theme-primary);
119
- border-left-style: solid;
120
- border-left-width: calc(var(--su-static1) * 3); // 3px
121
- content: '';
122
- height: calc(100% + @sw-content-spacing-inner);
123
- left: 0;
124
- margin-left: calc(@sw-content-px * -1 - var(--su-static1)); // the orange selection indicator overlaps with the widget border
125
- margin-top: calc(@sw-content-spacing-inner / 2 * -1);
126
- position: absolute;
127
- }
128
-
129
- a { // TODO: this isn't the best way to go about this. There should be a "is current" highlight without font modification for more complex cases
130
- &,
131
- &:visited {
132
- color: inherit;
133
- }
134
- }
135
-
136
- color: var(--black);
137
- font-weight: bold;
138
- position: relative;
139
- }
140
- }
141
-
142
- margin: @sw-content-spacing-inner 0;
143
- }
144
-
145
- & &--subnav {
146
- li {
147
- &[aria-current="page"],
148
- &[aria-current="true"] {
149
- a {
150
- &,
151
- &:visited {
152
- color: inherit;
153
- }
154
- }
155
-
156
- #stacks-internals #bullet-arrow(var(--theme-primary));
157
- color: var(--black);
158
- font-weight: bold;
159
- }
160
-
161
- #stacks-internals #bullet-arrow(var(--black-225));
162
- background-position: 0 calc((1.2em - calc(var(--su-static8) + var(--su-static2))) / 2); // 0 ((1.2em - 10) / 2)
163
- background-repeat: no-repeat;
164
- background-size: auto calc(var(--su-static8) + var(--su-static2)); // auto 10px
165
- margin-top: var(--su-static12);
166
- padding-left: var(--su-static16);
167
- }
168
-
169
- list-style-type: none;
170
- margin-left: var(--su8);
171
- padding-left: 0;
172
- }
173
-
174
- & table&--content&__items {
175
- tr.s-sidebarwidget--item {
176
- td {
177
- padding: 0;
178
- }
179
-
180
- display: table-row;
181
- }
182
-
183
- border-collapse: separate;
184
- border-spacing: @sw-content-spacing-inner;
185
- padding: calc(@sw-content-spacing-outer - @sw-content-spacing-inner) calc(@sw-content-px - @sw-content-spacing-inner);
186
- }
187
-
188
- &:before { // [1]
189
- content: '';
190
- display: block;
191
- margin-top: calc(var(--su-static1) * -1); // -1px
192
- }
193
-
194
- &:after { // [2]
195
- border: var(--su-static1) solid var(--_sw-after-bc);
196
- border-radius: var(--br-sm);
197
- clip-path: polygon(0% 0%, 100% 0%, 100% 50%, 0% 50%); // [3]
198
- content: '';
199
- // TODO: this makes no sense. revisit.
200
- height: calc(var(--su-static2) + var(--br-sm)); // we need 2px border + 2px border radius to have the correct corner shape
201
- left: calc(var(--su-static1) * -1); // -1px
202
- pointer-events: none; // if the top item is clickable, then we don't want to prevent clicking the top 2 pixels
203
- position: absolute;
204
- right: calc(var(--su-static1) * -1); // -1px
205
- top: calc(var(--su-static1) * -1); // -1px
206
- }
207
-
208
- background-color: var(--white);
209
- border: var(--su-static1) solid var(--_sw-bc);
210
- border-radius: var(--br-sm);
211
- font-size: var(--fs-body1);
212
- position: relative; // so that it's the positioning parent for the :after
213
- }
214
-
215
- // COLOR ALTERNATIVES
216
- .alternate-color(@name) {
217
- &.s-sidebarwidget__@{name} {
218
- --_sw-bc: var(~"--@{name}-300");
219
-
220
- .highcontrast-mode({
221
- --_sw-bc: var(~"--@{name}-500");
222
- });
223
-
224
- &:after,
225
- .s-sidebarwidget--content,
226
- .s-sidebarwidget--header {
227
- border-color: var(--_sw-bc);
228
- }
229
-
230
- .s-sidebarwidget--header {
231
- background-color: var(~"--@{name}-200");
232
- color: var(--fc-medium);
233
- }
234
-
235
- background-color: var(~"--@{name}-100");
236
- border-color: var(--_sw-bc);
237
- }
238
- }
239
-
240
- // [1] We must support things like collapsible (in particular invisble) elements, wrapper elements,
241
- // etc. Therefore every .-content and .-header must stand on its own; we cannot rely on things
242
- // like :first-child, because the *first* child may not be the first *visible* child, and it may
243
- // also be the :first-child of some wrapper. This is why every .-header and .-content has a
244
- // border-top. But because you shouldn't see the first visible item's or header's top border
245
- // (the widget itself provides for that border), we shift everything up by one pixel with the following pseudo-element.
246
-
247
- // [2] The top item's divider line sits above the .s-sidebarwidget's top border.
248
- // We could fix this by using overflow: hidden, but that would constrain users of
249
- // .s-sidebarwidget to never have things like tooltips, autocompletes or the like that reach
250
- // outside the widget boundaries.
251
- // What we do instead is re-create the widget's top border in an absolutely positioned :after,
252
- // which sits above our item's top border. Technically, a tiny corner of the item's border will
253
- // still be visible, but at its highest point, this corner has a height of 0.27 pixels. And for
254
- // this sub-pixel issues, we're talking about different shades of gray. So we can live with that.
255
-
256
- // [3] In order to perfectly recreate the inner corner shape, our pseudo-element needs
257
- // the border on all sides. But we can only do that if we're able to hide the bottom part.
1
+ .s-sidebarwidget {
2
+ // COMPONENT-SPECIFIC CONSTANTS
3
+ @sw-content-px: calc(var(--su16) - var(--su1)); // subtract 1px for border
4
+ @sw-content-spacing-inner: var(--su12); // the spacing between two adjacent simple items
5
+ @sw-content-spacing-outer: var(--su16); // the spacing at the start/end of a group of simple items, as well as between a complex item and its separator line
6
+ // COMPONENT-SPECIFIC CUSTOM PROPERTIES
7
+ --_sw-bc: var(--bc-medium);
8
+ --_sw-after-bc: var(--_sw-bc);
9
+ --_sw-content-bc: var(--bc-light);
10
+ --_sw-header-bc: var(--_sw-content-bc);
11
+
12
+ // MODIFIERS
13
+ &:not(.s-anchors) {
14
+ a:not(.button):not(.post-tag):not(.s-btn):not(.s-sidebarwidget--action):not(.s-user-card--link) {
15
+ &,
16
+ &:visited {
17
+ color: var(--black-400);
18
+ }
19
+ }
20
+ }
21
+
22
+ // VARIANTS
23
+ .alternate-color(blue);
24
+ .alternate-color(yellow);
25
+ .alternate-color(green);
26
+
27
+ // CHILD ELEMENTS
28
+ & &--action {
29
+ color: var(--blue-400);
30
+ float: right;
31
+ font-size: var(--fs-fine);
32
+ line-height: calc(var(--fs-body1) * 1.5); // 19.5px - line-height should be the same as in the outside element, so the header and action baselines line up
33
+ margin: 0 0 var(--su4) var(--su8);
34
+ }
35
+
36
+ & &--content {
37
+ &:not(table) {
38
+ &:not(.s-sidebarwidget__items),
39
+ &:not(.s-sidebarwidget__block-items) .s-sidebarwidget--item {
40
+ display: flex;
41
+ }
42
+ }
43
+
44
+ &.s-sidebarwidget__items {
45
+ &,
46
+ &.s-sidebarwidget__block-items .s-sidebarwidget--item {
47
+ display: block;
48
+ }
49
+
50
+ padding: calc(@sw-content-spacing-outer - @sw-content-spacing-inner) @sw-content-px; // the items themselves provide part of the spacing, so the content padding needs to account for that
51
+ }
52
+
53
+ &:active {
54
+ outline: none;
55
+ }
56
+
57
+ border-top: var(--su-static1) solid var(--_sw-content-bc);
58
+ margin: 0;
59
+ padding: @sw-content-spacing-outer @sw-content-px;
60
+ }
61
+
62
+ & &--header {
63
+ &:first-child {
64
+ border-top-left-radius: var(--br-sm);
65
+ border-top-right-radius: var(--br-sm);
66
+ }
67
+
68
+ &.s-sidebarwidget {
69
+ &__expanding-control {
70
+ &:before {
71
+ border: calc(var(--su-static4) + var(--su-static1)) solid transparent;
72
+ border-left-color: var(--black-400);
73
+ border-right-width: 0;
74
+ content: '';
75
+ float: left;
76
+ margin-right: var(--su12);
77
+ margin-top: calc(calc(var(--lh-base) * 1em) / 2 - 5px); // 1.3 is our standard line height
78
+ transition: transform 0.3s cubic-bezier(0.4, 0.4, 0.6, 1);
79
+ }
80
+
81
+ &[aria-expanded='true']:before {
82
+ transform: rotate(90deg);
83
+ }
84
+
85
+ cursor: pointer;
86
+ }
87
+
88
+ &__small-bold-text {
89
+ .s-sidebarwidget--action {
90
+ font-weight: normal;
91
+ line-height: calc(var(--lh-base) * var(--fs-caption)); // line-height should be the same as in the outside element, so the header and action baselines line up
92
+ }
93
+
94
+ font-size: var(--fs-caption);
95
+ font-weight: bold;
96
+ }
97
+ }
98
+
99
+ &:active {
100
+ outline: none;
101
+ }
102
+
103
+ background: var(--black-100);
104
+ border-top: var(--su-static1) solid var(--_sw-header-bc);
105
+ color: var(--black-500);
106
+ font-size: var(--fs-body2);
107
+ font-weight: normal;
108
+ margin: 0;
109
+ padding: @sw-content-spacing-inner @sw-content-px;
110
+ }
111
+
112
+ & &--item {
113
+ &,
114
+ & > :first-child {
115
+ &[aria-current="true"],
116
+ &[aria-current="page"] {
117
+ &:before {
118
+ border-left-color: var(--theme-primary);
119
+ border-left-style: solid;
120
+ border-left-width: calc(var(--su-static1) * 3); // 3px
121
+ content: '';
122
+ height: calc(100% + @sw-content-spacing-inner);
123
+ left: 0;
124
+ margin-left: calc(@sw-content-px * -1 - var(--su-static1)); // the orange selection indicator overlaps with the widget border
125
+ margin-top: calc(@sw-content-spacing-inner / 2 * -1);
126
+ position: absolute;
127
+ }
128
+
129
+ a { // TODO: this isn't the best way to go about this. There should be a "is current" highlight without font modification for more complex cases
130
+ &,
131
+ &:visited {
132
+ color: inherit;
133
+ }
134
+ }
135
+
136
+ color: var(--black);
137
+ font-weight: bold;
138
+ position: relative;
139
+ }
140
+ }
141
+
142
+ margin: @sw-content-spacing-inner 0;
143
+ }
144
+
145
+ & &--subnav {
146
+ li {
147
+ &[aria-current="page"],
148
+ &[aria-current="true"] {
149
+ a {
150
+ &,
151
+ &:visited {
152
+ color: inherit;
153
+ }
154
+ }
155
+
156
+ #stacks-internals #bullet-arrow(var(--theme-primary));
157
+ color: var(--black);
158
+ font-weight: bold;
159
+ }
160
+
161
+ #stacks-internals #bullet-arrow(var(--black-225));
162
+ background-position: 0 calc((1.2em - calc(var(--su-static8) + var(--su-static2))) / 2); // 0 ((1.2em - 10) / 2)
163
+ background-repeat: no-repeat;
164
+ background-size: auto calc(var(--su-static8) + var(--su-static2)); // auto 10px
165
+ margin-top: var(--su-static12);
166
+ padding-left: var(--su-static16);
167
+ }
168
+
169
+ list-style-type: none;
170
+ margin-left: var(--su8);
171
+ padding-left: 0;
172
+ }
173
+
174
+ & table&--content&__items {
175
+ tr.s-sidebarwidget--item {
176
+ td {
177
+ padding: 0;
178
+ }
179
+
180
+ display: table-row;
181
+ }
182
+
183
+ border-collapse: separate;
184
+ border-spacing: @sw-content-spacing-inner;
185
+ padding: calc(@sw-content-spacing-outer - @sw-content-spacing-inner) calc(@sw-content-px - @sw-content-spacing-inner);
186
+ }
187
+
188
+ &:before { // [1]
189
+ content: '';
190
+ display: block;
191
+ margin-top: calc(var(--su-static1) * -1); // -1px
192
+ }
193
+
194
+ &:after { // [2]
195
+ border: var(--su-static1) solid var(--_sw-after-bc);
196
+ border-radius: var(--br-sm);
197
+ clip-path: polygon(0% 0%, 100% 0%, 100% 50%, 0% 50%); // [3]
198
+ content: '';
199
+ // TODO: this makes no sense. revisit.
200
+ height: calc(var(--su-static2) + var(--br-sm)); // we need 2px border + 2px border radius to have the correct corner shape
201
+ left: calc(var(--su-static1) * -1); // -1px
202
+ pointer-events: none; // if the top item is clickable, then we don't want to prevent clicking the top 2 pixels
203
+ position: absolute;
204
+ right: calc(var(--su-static1) * -1); // -1px
205
+ top: calc(var(--su-static1) * -1); // -1px
206
+ }
207
+
208
+ background-color: var(--white);
209
+ border: var(--su-static1) solid var(--_sw-bc);
210
+ border-radius: var(--br-sm);
211
+ font-size: var(--fs-body1);
212
+ position: relative; // so that it's the positioning parent for the :after
213
+ }
214
+
215
+ // COLOR ALTERNATIVES
216
+ .alternate-color(@name) {
217
+ &.s-sidebarwidget__@{name} {
218
+ --_sw-bc: var(~"--@{name}-300");
219
+
220
+ .highcontrast-mode({
221
+ --_sw-bc: var(~"--@{name}-500");
222
+ });
223
+
224
+ &:after,
225
+ .s-sidebarwidget--content,
226
+ .s-sidebarwidget--header {
227
+ border-color: var(--_sw-bc);
228
+ }
229
+
230
+ .s-sidebarwidget--header {
231
+ background-color: var(~"--@{name}-200");
232
+ color: var(--fc-medium);
233
+ }
234
+
235
+ background-color: var(~"--@{name}-100");
236
+ border-color: var(--_sw-bc);
237
+ }
238
+ }
239
+
240
+ // [1] We must support things like collapsible (in particular invisble) elements, wrapper elements,
241
+ // etc. Therefore every .-content and .-header must stand on its own; we cannot rely on things
242
+ // like :first-child, because the *first* child may not be the first *visible* child, and it may
243
+ // also be the :first-child of some wrapper. This is why every .-header and .-content has a
244
+ // border-top. But because you shouldn't see the first visible item's or header's top border
245
+ // (the widget itself provides for that border), we shift everything up by one pixel with the following pseudo-element.
246
+
247
+ // [2] The top item's divider line sits above the .s-sidebarwidget's top border.
248
+ // We could fix this by using overflow: hidden, but that would constrain users of
249
+ // .s-sidebarwidget to never have things like tooltips, autocompletes or the like that reach
250
+ // outside the widget boundaries.
251
+ // What we do instead is re-create the widget's top border in an absolutely positioned :after,
252
+ // which sits above our item's top border. Technically, a tiny corner of the item's border will
253
+ // still be visible, but at its highest point, this corner has a height of 0.27 pixels. And for
254
+ // this sub-pixel issues, we're talking about different shades of gray. So we can live with that.
255
+
256
+ // [3] In order to perfectly recreate the inner corner shape, our pseudo-element needs
257
+ // the border on all sides. But we can only do that if we're able to hide the bottom part.
@@ -1,58 +1,63 @@
1
- import { html, fixture } from "@open-wc/testing";
2
- import { visualDiff } from "@web/test-runner-visual-regression";
3
- import { screen } from "@testing-library/dom";
4
- import { generateTestVariations, type TestVariationArgs } from "./test-utils";
5
-
6
- type VisualTestArgs = TestVariationArgs;
7
-
8
- const scheduleVisualTest = ({
9
- element,
10
- testid,
11
- theme,
12
- }: {
13
- element: ReturnType<typeof html>;
14
- testid: string;
15
- theme: string[];
16
- }) => {
17
- it(`visual: ${testid} should not introduce visual regressions`, async () => {
18
- document.body.className = "";
19
-
20
- if (theme?.length) {
21
- const prefixedThemes = theme.map((t) => `theme-${t}`);
22
- document.body.classList.add(...prefixedThemes);
23
- }
24
-
25
- let retryAttempts = 3;
26
-
27
- do {
28
- await fixture(element);
29
- const el = screen.getByTestId(testid);
30
- try {
31
- await visualDiff(el, testid);
32
- return;
33
- } catch (error) {
34
- const e = error as Error;
35
- // if the error is not a visual diff failure, retry
36
- // this is to prevent flaky tests due to snapshot capturing
37
- if (
38
- retryAttempts > 0 &&
39
- !e.message.includes("Visual diff failed.")
40
- ) {
41
- retryAttempts--;
42
- continue;
43
- } else {
44
- throw e;
45
- }
46
- } finally {
47
- el.remove();
48
- }
49
- } while (retryAttempts > 0);
50
- });
51
- };
52
-
53
- const runVisualTests = (args: VisualTestArgs) => {
54
- const testVariations = generateTestVariations(args);
55
- testVariations.forEach(scheduleVisualTest);
56
- };
57
-
58
- export { runVisualTests };
1
+ import { html, fixture } from "@open-wc/testing";
2
+ import { visualDiff } from "@web/test-runner-visual-regression";
3
+ import { screen } from "@testing-library/dom";
4
+ import { generateTestVariations, type TestVariationArgs } from "./test-utils";
5
+
6
+ type VisualTestArgs = TestVariationArgs;
7
+
8
+ const scheduleVisualTest = ({
9
+ element,
10
+ testid,
11
+ theme,
12
+ }: {
13
+ element: ReturnType<typeof html>;
14
+ testid: string;
15
+ theme: string[];
16
+ }) => {
17
+ it(`visual: ${testid} should not introduce visual regressions`, async () => {
18
+ document.body.className = "";
19
+
20
+ if (theme?.length) {
21
+ const prefixedThemes = theme.map((t) => `theme-${t}`);
22
+ document.body.classList.add(...prefixedThemes);
23
+ }
24
+
25
+ let retryAttempts = 3;
26
+
27
+ do {
28
+ await fixture(element);
29
+ const el = screen.getByTestId(testid);
30
+ try {
31
+ await (
32
+ visualDiff as (
33
+ element: HTMLElement,
34
+ name: string
35
+ ) => Promise<void>
36
+ )(el, testid);
37
+ return;
38
+ } catch (error) {
39
+ const e = error as Error;
40
+ // if the error is not a visual diff failure, retry
41
+ // this is to prevent flaky tests due to snapshot capturing
42
+ if (
43
+ retryAttempts > 0 &&
44
+ !e.message.includes("Visual diff failed.")
45
+ ) {
46
+ retryAttempts--;
47
+ continue;
48
+ } else {
49
+ throw e;
50
+ }
51
+ } finally {
52
+ el.remove();
53
+ }
54
+ } while (retryAttempts > 0);
55
+ });
56
+ };
57
+
58
+ const runVisualTests = (args: VisualTestArgs) => {
59
+ const testVariations = generateTestVariations(args);
60
+ testVariations.forEach(scheduleVisualTest);
61
+ };
62
+
63
+ export { runVisualTests };