@stackoverflow/stacks 2.3.0 → 2.3.2

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.
@@ -25,7 +25,7 @@ a.s-block-link,
25
25
  &&__left,
26
26
  &&__right {
27
27
  &.is-selected {
28
- &:not(:focus-visible) {
28
+ &:not(:focus-visible):not(.focus-inset) {
29
29
  box-shadow: inset var(--_li-block-bs-offset-x, 3px) 0 0 var(--_bl-bs-color);
30
30
  }
31
31
  }
@@ -57,10 +57,14 @@ a.s-block-link,
57
57
  }
58
58
 
59
59
  &:focus-visible {
60
- border-radius: var(--br-sm);
61
60
  .focus-styles(true);
62
61
  }
63
62
 
63
+ &:focus-visible,
64
+ &.focus-inset {
65
+ border-radius: var(--br-sm);
66
+ }
67
+
64
68
  background-color: var(--_bl-bg); // [1]
65
69
  color: var(--_bl-fc);
66
70
 
@@ -409,15 +409,14 @@
409
409
  }
410
410
 
411
411
  &:not(&--radio:checked + label):not(&__link):not(&__unset):not(&__facebook):not(&__github):not(&__google):not(.is-selected) {
412
- &:focus-visible {
413
- &.s-btn__filled {
414
- &:not(:hover) .s-btn--number {
415
- color: var(--_bu-number-fc-focus, var(--_bu-number-fc-filled));
416
- }
417
-
418
- background-color: var(--_bu-bg-focus, var(--_bu-filled-bg));
419
- color: var(--_bu-fc-focus, var(--_bu-filled-fc));
412
+ &:focus-visible,
413
+ &.focus-inset-bordered {
414
+ &:not(:hover) .s-btn--number {
415
+ color: var(--_bu-number-fc-focus, var(--_bu-number-fc-filled));
420
416
  }
417
+
418
+ background-color: var(--_bu-bg-focus, var(--_bu-filled-bg));
419
+ color: var(--_bu-fc-focus, var(--_bu-filled-fc));
421
420
  }
422
421
 
423
422
  &:hover {
@@ -20,24 +20,27 @@
20
20
  margin-right: calc(var(--su-static1) * -1); // -1px
21
21
  }
22
22
 
23
+ // --_bu-py values set below to ensure btn-group height matches same-sized button height
24
+ // See https://github.com/StackEng/StackOverflow/pull/18992#pullrequestreview-1947490680
23
25
  .s-btn {
24
26
  --_bu-br: var(--br-sm);
25
27
  --_bu-bc-hover: transparent;
28
+ --_bu-px: calc(var(--su12) - var(--su1)); // 11px
29
+ --_bu-py: calc(var(--su6) + 0.65px); // 6.65px
26
30
 
27
- &,
28
- &.s-btn__md {
29
- --_bu-px: var(--su12);
30
- --_bu-py: var(--su8);
31
+ &.s-btn__xs {
32
+ --_bu-px: calc(var(--su8) - var(--su1)); // 7px
33
+ --_bu-py: calc(var(--su2) + 0.9px); // 2.9px
31
34
  }
32
35
 
33
- &.s-btn___xs {
34
- --_bu-px: var(--su8);
35
- --_bu-py: var(--su4);
36
+ &.s-btn__sm {
37
+ --_bu-px: calc(var(--su8) + var(--su1)); // 9px
38
+ --_bu-py: calc(var(--su4) + (var(--su2) - 0.15px)); // 5.85px
36
39
  }
37
40
 
38
- &.s-btn___sm {
39
- --_bu-px: calc(var(--su8) + var(--su2));
40
- --_bu-py: var(--su6);
41
+ &.s-btn__md {
42
+ --_bu-px: var(--su12);
43
+ --_bu-py: calc(var(--su8) + 0.15px); // 8.15px
41
44
  }
42
45
 
43
46
  &.is-selected,
@@ -46,6 +49,9 @@
46
49
  }
47
50
 
48
51
  .s-btn--badge {
52
+ // set negative margins so button height isn't affect by badge
53
+ margin-bottom: -100%;
54
+ margin-top: -100%;
49
55
  font-weight: normal;
50
56
  }
51
57
 
@@ -70,8 +76,7 @@
70
76
  // STATIC COMPONENT STYLES
71
77
  border: var(--su-static1) solid var(--black-300);
72
78
  border-radius: var(--br-md);
73
- display: inline-flex; // TODO investigate if changing from flex to inline-flex will be an issue
79
+ display: inline-flex;
74
80
  flex-wrap: wrap;
75
- margin-bottom: var(--su-static1); // Compensate for buttons having a margin bottom of -1px to account for row wrapping
76
81
  padding: calc(var(--su-static4) - var(--su-static1));
77
82
  }
@@ -9,7 +9,7 @@ describe("notice", () => {
9
9
  primary: ["important"],
10
10
  },
11
11
  children: {
12
- default: `Test notice`,
12
+ default: `Test notice <code>some code</code> <a class="s-link s-link__inherit s-link__underlined" href="#">Link</a>`,
13
13
  },
14
14
  tag: "aside",
15
15
  });
@@ -1,107 +1,129 @@
1
+ /**
2
+ * Generate color variables with a given color name
3
+ *
4
+ * Usage example:
5
+ * .generate-variant-variables(purple, important);
6
+ *
7
+ * @colorName - The name of the color to use to construct variables values
8
+ * @modifier - Modifier name to determine variable values for that modifier
9
+ */
10
+ .generate-variant-variables(@colorName: "", @modifier: "") {
11
+ & when (@modifier = "") {
12
+ --_no-bc: ~"var(--@{colorName}-300)";
13
+ --_no-bg: ~"var(--@{colorName}-100)";
14
+ --_no-btn-bg-active: ~"var(--@{colorName}-200)";
15
+ --_no-btn-bg-focus: ~"var(--@{colorName}-200)";
16
+ --_no-btn-fc: ~"var(--@{colorName}-500)";
17
+ --_no-code-bc: ~"var(--@{colorName}-300)";
18
+ --_no-code-bg: ~"var(--@{colorName}-200)";
19
+ }
20
+
21
+ & when (@modifier = important) {
22
+ --_no-bc: var(--_no-bg);
23
+ --_no-bg: ~"var(--@{colorName}-400)";
24
+ --_no-fc: var(--white);
25
+ --_no-btn-bg-active: ~"var(--@{colorName}-500)";
26
+ --_no-btn-bg-focus: ~"var(--@{colorName}-500)";
27
+ --_no-btn-fc: ~"var(--@{colorName}-100)";
28
+ --_no-code-bc: ~"var(--@{colorName}-300)";
29
+ --_no-code-bg: ~"var(--@{colorName}-500)";
30
+
31
+ .highcontrast-mode({
32
+ --_no-bg: ~"var(--@{colorName}-500)";
33
+ });
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Generate styles for a notice-based component
39
+ *
40
+ * Usage example:
41
+ * .construct-notice-component(s-banner);
42
+ *
43
+ * @baseClass - The base class name for the notice component
44
+ */
1
45
  .construct-notice-component(@baseClass) {
2
46
  --_no-bc: var(--black-225);
3
47
  --_no-bg: var(--black-100);
4
48
  --_no-fc: var(--black-500);
5
- --_no-btn-bg-focus: var(--black-225);
6
49
  --_no-btn-bg-active: var(--black-250);
50
+ --_no-btn-bg-focus: var(--black-225);
7
51
  --_no-btn-fc: var(--_no-fc);
52
+ --_no-code-bc: var(--black-300);
53
+ --_no-code-bg: var(--black-200);
54
+ --_no-code-fc: var(--_no-fc);
8
55
 
9
- // MODIFIERS
10
- &:not(&__important) {
11
- .dark-mode({
12
- --_no-bc: var(--_no-bg);
13
- });
14
-
15
- .highcontrast-mode({
16
- --_no-bc: currentColor;
17
- });
18
-
19
- .highcontrast-dark-mode({
20
- --_no-bc: currentColor;
21
- });
22
- }
56
+ // CONTEXTUAL STYLES
57
+ .dark-mode({
58
+ --_no-bc: var(--_no-bg);
59
+ });
60
+
61
+ .highcontrast-mode({
62
+ &,
63
+ &.@{baseClass}__danger,
64
+ &.@{baseClass}__info,
65
+ &.@{baseClass}__success,
66
+ &.@{baseClass}__warning {
67
+ --_no-code-bc: var(--black-400);
68
+ --_no-code-bg: var(--white);
69
+ --_no-code-fc: var(--black);
70
+
71
+ &.@{baseClass}__important {
72
+ --_no-code-bc: var(--black-200);
73
+ --_no-code-bg: var(--black);
74
+ --_no-code-fc: var(--white);
75
+ }
76
+ }
77
+ });
23
78
 
24
- &__important {
79
+ // MODIFIERS
80
+ &__important:not(.@{baseClass}__danger):not(.@{baseClass}__info):not(.@{baseClass}__success):not(.@{baseClass}__warning) {
25
81
  --_no-bc: var(--_no-bg);
26
82
  --_no-bg: var(--black-500);
27
83
  --_no-fc: var(--white);
28
84
  --_no-btn-bg-focus: var(--black-600);
29
85
  --_no-btn-bg-active: var(--black-600);
30
86
  --_no-btn-fc: var(--_no-fc);
31
- --_no-code-bg: var(--black-300);
87
+ --_no-code-bc: var(--black-300);
88
+ --_no-code-bg: var(--black-600);
32
89
  }
33
90
 
34
91
  // VARIANTS
35
92
  &__danger {
36
- --_no-bc: var(--red-300);
37
- --_no-bg: var(--red-100);
38
- --_no-btn-bg-active: var(--red-200);
39
- --_no-btn-bg-focus: var(--red-200);
40
- --_no-btn-fc: var(--red-500);
41
- --_no-code-bg: var(--red-300);
93
+ &:not(.@{baseClass}__important) {
94
+ .generate-variant-variables(red);
95
+ }
42
96
 
43
97
  &.@{baseClass}__important {
44
- --_no-bc: var(--_no-bg);
45
- --_no-bg: var(--red-400);
46
- --_no-btn-bg-active: var(--red-500);
47
- --_no-btn-bg-focus: var(--red-500);
48
- --_no-btn-fc: var(--red-100);
49
-
50
- .highcontrast-mode({
51
- --_no-bg: var(--red-500);
52
- });
98
+ .generate-variant-variables(red, important);
53
99
  }
54
100
  }
55
101
 
56
102
  &__info {
57
- --_no-bc: var(--theme-secondary-300);
58
- --_no-bg: var(--theme-secondary-100);
59
- --_no-btn-bg-focus: var(--theme-secondary-200);
60
- --_no-btn-bg-active: var(--theme-secondary-200);
61
- --_no-btn-fc: var(--theme-secondary-500);
62
- --_no-code-bg: var(--theme-secondary-300);
103
+ &:not(.@{baseClass}__important) {
104
+ .generate-variant-variables(theme-secondary);
105
+ }
63
106
 
64
107
  &.@{baseClass}__important {
65
- --_no-bc: var(--_no-bg);
66
- --_no-bg: var(--theme-secondary-400);
67
- --_no-btn-bg-active: var(--theme-secondary-500);
68
- --_no-btn-bg-focus: var(--theme-secondary-500);
69
- --_no-btn-fc: var(--theme-secondary-100);
70
-
71
- .highcontrast-mode({
72
- --_no-bg: var(--theme-secondary-500);
73
- });
108
+ .generate-variant-variables(theme-secondary, important);
74
109
  }
75
110
  }
76
111
 
77
112
  &__success {
78
- --_no-bc: var(--green-300);
79
- --_no-bg: var(--green-100);
80
- --_no-btn-bg-active: var(--green-200);
81
- --_no-btn-bg-focus: var(--green-200);
82
- --_no-btn-fc: var(--green-500);
83
- --_no-code-bg: var(--green-300);
113
+ &:not(.@{baseClass}__important) {
114
+ .generate-variant-variables(green);
115
+ }
84
116
 
85
117
  &.@{baseClass}__important {
86
- --_no-bc: var(--_no-bg);
87
- --_no-bg: var(--green-400);
88
- --_no-btn-bg-active: var(--green-500);
89
- --_no-btn-bg-focus: var(--green-500);
90
- --_no-btn-fc: var(--green-100);
91
-
92
- .highcontrast-mode({
93
- --_no-bg: var(--green-500);
94
- });
118
+ .generate-variant-variables(green, important);
95
119
  }
96
120
  }
97
121
 
98
122
  &__warning {
99
- --_no-bc: var(--yellow-300);
100
- --_no-bg: var(--yellow-100);
101
- --_no-btn-bg-active: var(--yellow-200);
102
- --_no-btn-bg-focus: var(--yellow-200);
103
- --_no-btn-fc: var(--yellow-600);
104
- --_no-code-bg: var(--yellow-300);
123
+ &:not(.@{baseClass}__important) {
124
+ .generate-variant-variables(yellow);
125
+ --_no-btn-fc: var(--yellow-600);
126
+ }
105
127
 
106
128
  &.@{baseClass}__important {
107
129
  --_no-bc: var(--_no-bg);
@@ -110,9 +132,13 @@
110
132
  --_no-btn-fc: var(--_no-fc);
111
133
  --_no-btn-bg-active: var(--yellow-300);
112
134
  --_no-btn-bg-focus: var(--yellow-300);
135
+ --_no-code-bc: var(--yellow-500);
136
+ --_no-code-bg: var(--yellow-300);
113
137
 
114
138
  .dark-mode({
115
- --_no-fc: var(--yellow-200);
139
+ --_no-fc: var(--white);
140
+ --_no-code-bc: var(--yellow-300);
141
+ --_no-code-bg: var(--yellow-500);
116
142
  });
117
143
 
118
144
  .highcontrast-mode({
@@ -126,21 +152,24 @@
126
152
 
127
153
  // CHILD ELEMENTS
128
154
  code {
129
- background: var(--_no-code-bg, transparent);
155
+ background-color: var(--_no-code-bg);
156
+ color: var(--_no-code-fc);
157
+ outline: var(--su-static1) solid var(--_no-code-bc);
158
+
159
+ border-radius: var(--br-sm);
160
+ padding-left: var(--su2);
161
+ padding-right: var(--su2);
130
162
  }
131
163
 
132
164
  & &--btn {
133
165
  // TODO: decouple .s-notice--btn from .s-btn
134
- &:not(:focus) {
135
- box-shadow: none; // This will prevent default .s-btn box-shadow from showing
136
- }
137
-
138
166
  &:active {
139
167
  background-color: var(--_no-btn-bg-active, inherit) !important;
140
168
  }
141
169
 
142
- &:focus,
143
- &:hover {
170
+ &:focus-visible,
171
+ &:hover,
172
+ &.focus-inset-bordered {
144
173
  background-color: var(--_no-btn-bg-focus, inherit) !important;
145
174
  }
146
175
 
@@ -13,11 +13,11 @@ describe("notice", () => {
13
13
  ariaHidden: "false",
14
14
  },
15
15
  children: {
16
- default: `Test notice`,
16
+ default: `Test notice <code>some code</code> <a class="s-link s-link__inherit s-link__underlined" href="#">Link</a>`,
17
17
  },
18
18
  tag: "aside",
19
19
  template: ({ component, testid }) => html`
20
- <div class="d-inline-block p8" data-testid="${testid}">
20
+ <div class="d-inline-block p8 wmx5" data-testid="${testid}">
21
21
  ${component}
22
22
  </div>
23
23
  `,
@@ -40,9 +40,13 @@
40
40
  }
41
41
 
42
42
  &:focus-visible {
43
+ .focus-styles(true, true);
44
+ }
45
+
46
+ &:focus-visible,
47
+ &.focus-inset-bordered {
43
48
  background-color: var(--_pa-item-bg-focus);
44
49
  color: var(--_pa-item-fc-focus);
45
- .focus-styles(true, true);
46
50
  }
47
51
 
48
52
  background-color: var(--_pa-item-bg);
@@ -67,7 +67,8 @@
67
67
  &,
68
68
  &:active,
69
69
  &:hover,
70
- &:focus {
70
+ &:focus,
71
+ .focus-bordered {
71
72
  .highcontrast-mode({
72
73
  border-color: currentColor;
73
74
  });
@@ -293,7 +293,7 @@ const getBadgeChildren = (badge: BadgeType) => {
293
293
  stats: true,
294
294
  },
295
295
  stats: {
296
- badge: badge as BadgeType,
296
+ badge: badge,
297
297
  answers: 0,
298
298
  votes: 1,
299
299
  views: 20,
@@ -100,10 +100,14 @@
100
100
 
101
101
  // INTERACTION
102
102
  &:focus {
103
- color: var(--black);
104
103
  .focus-styles();
105
104
  }
106
105
 
106
+ &:focus,
107
+ &.focus {
108
+ color: var(--black);
109
+ }
110
+
107
111
  background-color: var(--_se-select-bg);
108
112
  border: var(--su-static1) solid var(--_se-select-bc);
109
113
  border-radius: var(--_se-select-br);
@@ -90,23 +90,11 @@
90
90
  });
91
91
 
92
92
  #stacks-internals #screen-sm({
93
- & &--searchbar {
94
- --_tb-searchbar-d: none;
95
- --_tb-searchbar-p: var(--su8) var(--su12);
96
- --_tb-searchbar-open-d: flex;
97
- --_tb-searchbar-open-mxw: none;
98
-
99
- .s-select {
100
- width: 25% !important;
101
- }
102
-
103
- background: var(--theme-topbar-item-background-hover, var(--black-200));
104
- left: 0;
105
- max-width: 100%;
106
- position: absolute;
107
- right: 0;
108
- top: 100%;
109
- }
93
+ --_tb-searchbar-d: none;
94
+ --_tb-searchbar-p: var(--su8) var(--su12);
95
+ --_tb-searchbar-open-d: flex;
96
+ --_tb-searchbar-open-mxw: none;
97
+ --_tb-searchbar-select-w: 25%;
110
98
  });
111
99
 
112
100
  // VARIANTS
@@ -327,6 +315,15 @@
327
315
  }
328
316
 
329
317
  & &--searchbar {
318
+ #stacks-internals #screen-sm({
319
+ background: var(--theme-topbar-item-background-hover, var(--black-200));
320
+ left: 0;
321
+ max-width: 100%;
322
+ position: absolute;
323
+ right: 0;
324
+ top: 100%;
325
+ });
326
+
330
327
  .s-topbar--searchbar--input-group {
331
328
  .s-input {
332
329
  &::placeholder {
@@ -334,7 +331,7 @@
334
331
  font-style: normal;
335
332
  }
336
333
 
337
- &:not(:focus-visible) {
334
+ &:not(:focus-visible):not(.focus) {
338
335
  box-shadow: var(--theme-topbar-search-shadow);
339
336
  }
340
337
 
@@ -354,8 +351,13 @@
354
351
  }
355
352
 
356
353
  .s-select {
354
+ #stacks-internals #screen-sm({
355
+ width: 25% !important;
356
+ });
357
+
357
358
  > select {
358
- &:focus-visible {
359
+ &:focus-visible,
360
+ &.focus {
359
361
  z-index: var(--zi-selected);
360
362
  }
361
363
 
@@ -385,8 +387,10 @@
385
387
  }
386
388
 
387
389
  &.s-topbar--searchbar__open {
388
- display: var(--_tb-searchbar-open-d);
389
- max-width: var(--_tb-searchbar-open-mxw);
390
+ #stacks-internals #screen-sm({
391
+ display: var(--_tb-searchbar-open-d);
392
+ max-width: var(--_tb-searchbar-open-mxw);
393
+ });
390
394
  }
391
395
 
392
396
  display: var(--_tb-searchbar-d);
@@ -90,10 +90,14 @@
90
90
 
91
91
  & &--input {
92
92
  &:focus:focus-visible + .s-uploader--container {
93
- background-color: var(--_up-bg-focus);
94
93
  .focus-styles();
95
94
  }
96
95
 
96
+ &:focus:focus-visible + .s-uploader--container,
97
+ .s-uploader--container.focus {
98
+ background-color: var(--_up-bg-focus);
99
+ }
100
+
97
101
  cursor: pointer;
98
102
  height: 100%;
99
103
  inset: 0;
@@ -13,7 +13,7 @@ type A11yTestArgs = TestVariationArgs & {
13
13
  };
14
14
 
15
15
  // register Stack APCA conformance threshold function
16
- // see also https://stackoverflow.design/product/base/color-fundamentals/#accessibility-standards
16
+ // see also https://stackoverflow.design/product/foundation/accessibility/#visual-accessibility
17
17
  const customConformanceThresholdFn = (fontSize: string): number | null => {
18
18
  // if the font size is 32px or larger, we use a 45Lc threshold
19
19
  // otherwise, we use a 60Lc threshold
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "https://github.com/StackExchange/Stacks.git"
7
7
  },
8
- "version": "2.3.0",
8
+ "version": "2.3.2",
9
9
  "files": [
10
10
  "dist",
11
11
  "lib"
@@ -47,18 +47,18 @@
47
47
  "@open-wc/testing": "^4.0.0",
48
48
  "@rollup/plugin-commonjs": "^25.0.7",
49
49
  "@rollup/plugin-replace": "^5.0.5",
50
- "@stackoverflow/stacks-editor": "^0.10.2",
51
- "@stackoverflow/stacks-icons": "^6.0.1",
50
+ "@stackoverflow/stacks-editor": "^0.10.3",
51
+ "@stackoverflow/stacks-icons": "^6.0.2",
52
52
  "@testing-library/dom": "^9.3.4",
53
53
  "@testing-library/user-event": "^14.5.2",
54
54
  "@types/cssbeautify": "^0.3.5",
55
55
  "@types/less": "^3.0.6",
56
56
  "@types/mocha": "^10.0.6",
57
- "@typescript-eslint/eslint-plugin": "^7.1.0",
58
- "@typescript-eslint/parser": "^7.1.0",
57
+ "@typescript-eslint/eslint-plugin": "^7.3.1",
58
+ "@typescript-eslint/parser": "^7.3.1",
59
59
  "@web/dev-server-esbuild": "^1.0.2",
60
60
  "@web/dev-server-rollup": "^0.6.1",
61
- "@web/test-runner": "^0.18.0",
61
+ "@web/test-runner": "^0.18.1",
62
62
  "@web/test-runner-playwright": "^0.11.0",
63
63
  "@web/test-runner-visual-regression": "^0.9.0",
64
64
  "apca-check": "^0.1.0",
@@ -66,7 +66,7 @@
66
66
  "concurrently": "^8.2.2",
67
67
  "css-loader": "^6.10.0",
68
68
  "cssbeautify": "^0.3.1",
69
- "cssnano": "^6.0.5",
69
+ "cssnano": "^6.1.0",
70
70
  "docsearch.js": "^2.6.3",
71
71
  "eleventy-plugin-highlightjs": "^1.1.0",
72
72
  "eleventy-plugin-nesting-toc": "^1.3.0",
@@ -76,20 +76,20 @@
76
76
  "jquery": "^3.7.1",
77
77
  "less-loader": "^12.2.0",
78
78
  "list.js": "^2.3.1",
79
- "markdown-it": "^14.0.0",
79
+ "markdown-it": "^14.1.0",
80
80
  "mini-css-extract-plugin": "^2.8.1",
81
81
  "postcss-less": "^6.0.0",
82
82
  "postcss-loader": "^8.1.1",
83
83
  "prettier": "^3.2.5",
84
84
  "rollup-plugin-postcss": "^4.0.2",
85
- "stylelint": "^16.2.1",
85
+ "stylelint": "^16.3.0",
86
86
  "stylelint-config-recommended": "^14.0.0",
87
87
  "stylelint-config-standard": "^36.0.0",
88
88
  "terser-webpack-plugin": "^5.3.10",
89
89
  "ts-loader": "^9.5.1",
90
- "typescript": "^5.3.3",
91
- "vitest": "^1.3.1",
92
- "webpack": "^5.90.3",
90
+ "typescript": "^5.4.2",
91
+ "vitest": "^1.4.0",
92
+ "webpack": "^5.91.0",
93
93
  "webpack-cli": "^5.1.4",
94
94
  "webpack-merge": "^5.10.0"
95
95
  },