@stackoverflow/stacks 0.73.1 → 0.76.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.
Files changed (87) hide show
  1. package/LICENSE.MD +9 -9
  2. package/README.md +47 -47
  3. package/dist/controllers/index.d.ts +7 -0
  4. package/dist/controllers/s-expandable-control.d.ts +17 -0
  5. package/dist/controllers/s-modal.d.ts +97 -0
  6. package/dist/controllers/s-navigation-tablist.d.ts +36 -0
  7. package/dist/controllers/s-popover.d.ts +155 -0
  8. package/dist/controllers/s-table.d.ts +8 -0
  9. package/dist/controllers/s-tooltip.d.ts +82 -0
  10. package/dist/controllers/s-uploader.d.ts +48 -0
  11. package/dist/css/stacks.css +441 -141
  12. package/dist/css/stacks.min.css +1 -1
  13. package/dist/index.d.ts +3 -0
  14. package/dist/js/stacks.js +6130 -5488
  15. package/dist/js/stacks.min.js +1 -1
  16. package/dist/stacks.d.ts +21 -0
  17. package/lib/css/atomic/_stacks-borders.less +378 -378
  18. package/lib/css/atomic/_stacks-colors.less +209 -209
  19. package/lib/css/atomic/_stacks-flex.less +374 -374
  20. package/lib/css/atomic/_stacks-grid.less +174 -173
  21. package/lib/css/atomic/_stacks-misc.less +343 -342
  22. package/lib/css/atomic/_stacks-spacing.less +168 -162
  23. package/lib/css/atomic/_stacks-typography.less +273 -270
  24. package/lib/css/atomic/_stacks-width-height.less +195 -189
  25. package/lib/css/base/_stacks-body.less +44 -46
  26. package/lib/css/base/_stacks-configuration-static.less +59 -59
  27. package/lib/css/base/_stacks-icons.less +20 -20
  28. package/lib/css/base/_stacks-internals.less +220 -230
  29. package/lib/css/base/_stacks-reset-meyer.less +64 -64
  30. package/lib/css/base/_stacks-reset-normalize.less +449 -449
  31. package/lib/css/base/_stacks-reset.less +20 -20
  32. package/lib/css/components/_stacks-activity-indicator.less +45 -45
  33. package/lib/css/components/_stacks-avatars.less +189 -189
  34. package/lib/css/components/_stacks-badges.less +209 -209
  35. package/lib/css/components/_stacks-banners.less +80 -81
  36. package/lib/css/components/_stacks-blank-states.less +26 -26
  37. package/lib/css/components/_stacks-breadcrumbs.less +44 -44
  38. package/lib/css/components/_stacks-button-groups.less +104 -104
  39. package/lib/css/components/_stacks-buttons.less +658 -660
  40. package/lib/css/components/_stacks-cards.less +44 -44
  41. package/lib/css/components/_stacks-code-blocks.less +130 -130
  42. package/lib/css/components/_stacks-collapsible.less +104 -104
  43. package/lib/css/components/_stacks-inputs.less +728 -724
  44. package/lib/css/components/_stacks-link-previews.less +136 -136
  45. package/lib/css/components/_stacks-links.less +218 -218
  46. package/lib/css/components/_stacks-menu.less +47 -47
  47. package/lib/css/components/_stacks-modals.less +133 -133
  48. package/lib/css/components/_stacks-navigation.less +146 -146
  49. package/lib/css/components/_stacks-notices.less +233 -233
  50. package/lib/css/components/_stacks-page-titles.less +60 -60
  51. package/lib/css/components/_stacks-pagination.less +55 -55
  52. package/lib/css/components/_stacks-popovers.less +197 -197
  53. package/lib/css/components/_stacks-post-summary.less +425 -311
  54. package/lib/css/components/_stacks-progress-bars.less +331 -331
  55. package/lib/css/components/_stacks-prose.less +503 -503
  56. package/lib/css/components/_stacks-spinner.less +107 -107
  57. package/lib/css/components/_stacks-tables.less +341 -341
  58. package/lib/css/components/_stacks-tags.less +237 -209
  59. package/lib/css/components/_stacks-toggle-switches.less +144 -137
  60. package/lib/css/components/_stacks-topbar.less +425 -440
  61. package/lib/css/components/_stacks-uploader.less +210 -210
  62. package/lib/css/components/_stacks-user-cards.less +169 -193
  63. package/lib/css/components/_stacks-widget-dynamic.less +33 -33
  64. package/lib/css/components/_stacks-widget-static.less +272 -272
  65. package/lib/css/exports/_stacks-constants-colors.less +1112 -1098
  66. package/lib/css/exports/_stacks-constants-helpers.less +139 -139
  67. package/lib/css/exports/_stacks-constants-type.less +152 -91
  68. package/lib/css/exports/_stacks-exports.less +15 -15
  69. package/lib/css/exports/_stacks-mixins.less +220 -220
  70. package/lib/css/stacks-dynamic.less +35 -36
  71. package/lib/css/stacks-static.less +86 -86
  72. package/lib/ts/controllers/index.ts +8 -0
  73. package/lib/ts/controllers/s-expandable-control.ts +189 -190
  74. package/lib/ts/controllers/s-modal.ts +321 -323
  75. package/lib/ts/controllers/s-navigation-tablist.ts +118 -119
  76. package/lib/ts/controllers/s-popover.ts +547 -549
  77. package/lib/ts/controllers/s-table.ts +220 -220
  78. package/lib/ts/controllers/s-tooltip.ts +246 -247
  79. package/lib/ts/controllers/s-uploader.ts +172 -174
  80. package/lib/ts/index.ts +20 -0
  81. package/lib/ts/stacks.ts +88 -83
  82. package/lib/tsconfig.json +13 -11
  83. package/package.json +87 -71
  84. package/dist/css/stacks-flexgrid-shim.min.css +0 -1
  85. package/lib/css/base/_stacks-configuration-dynamic.less +0 -106
  86. package/lib/ts/finalize.ts +0 -1
  87. package/lib/ts/stimulus.d.ts +0 -4
@@ -1,440 +1,425 @@
1
- //
2
- // STACK OVERFLOW
3
- // TOPBAR
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
- // ============================================================================
10
- // $ BASE STYLE
11
- // ----------------------------------------------------------------------------
12
- .s-topbar {
13
- min-width: auto;
14
- box-shadow: var(--bs-sm);
15
- width: 100%;
16
- z-index: @zi-navigation-fixed;
17
- background-color: var(--theme-topbar-background-color);
18
- height: var(--theme-topbar-height);
19
- display: flex;
20
- border-top: var(--theme-topbar-accent-border);
21
- position: relative;
22
- align-items: center;
23
-
24
- // Redefine the variables for extra contrast in high-contrast mode
25
- .highcontrast-mode({
26
- // Search input
27
- --theme-topbar-search-color: var(--theme-topbar-item-color);
28
- --theme-topbar-search-background: var(--theme-topbar-background-color);
29
- --theme-topbar-search-placeholder: var(--theme-topbar-item-color);
30
- --theme-topbar-search-border: var(--theme-topbar-item-color);
31
- --theme-topbar-search-border-focus: var(--theme-topbar-item-color);
32
-
33
- // Search switcher
34
- --theme-topbar-select-color: var(--theme-topbar-item-color);
35
- --theme-topbar-select-background: var(--theme-topbar-background-color);
36
-
37
- // Topbar items
38
- --theme-topbar-item-color: var(--black-800);
39
- --theme-topbar-item-color-hover: var(--black-900);
40
- --theme-topbar-item-background-hover: var(--black-200);
41
- --theme-topbar-item-color-current: var(--black);
42
- });
43
-
44
- .highcontrast-mode({ border-bottom: 1px solid currentColor; });
45
-
46
- // Wraps the content so the topbar stretches 100% w/ content at some value below that
47
- .s-topbar--container {
48
- width: @s-full; // wmx12; Consumers should use atomic classes to override this
49
- max-width: 100%;
50
- height: 100%;
51
- display: flex;
52
- margin: 0 auto;
53
- align-items: center;
54
- }
55
-
56
- .s-topbar--logo {
57
- padding: 0 @su8;
58
- height: 100%;
59
- display: flex;
60
- align-items: center;
61
- background-color: transparent;
62
- }
63
-
64
- a.s-topbar--logo:hover {
65
- background-color: var(--theme-topbar-item-background-hover);
66
- }
67
-
68
- a.s-topbar--logo.is-selected {
69
- background-color: var(--theme-topbar-item-background-hover);
70
- }
71
-
72
- .s-topbar--menu-btn {
73
- display: flex;
74
- height: 100%;
75
- padding: 0 @su16;
76
- flex-shrink: 0;
77
- align-items: center;
78
- justify-content: center;
79
-
80
- // Build a hamburger icon manually using spans instead of using `@Svg` helper so
81
- // we can more easily animate its content and transform the hamburger into an x
82
- span {
83
- &,
84
- &:before,
85
- &:after {
86
- width: @su16;
87
- height: @su2;
88
- background-color: var(--theme-topbar-item-color);
89
- position: relative;
90
- }
91
-
92
- &:before,
93
- &:after {
94
- position: absolute;
95
- content: '';
96
- left: 0;
97
- top: -5px;
98
- transition: top, transform;
99
- transition-duration: 0.1s;
100
- transition-timing-function: ease-in-out;
101
- }
102
-
103
- &:after {
104
- top: 5px;
105
- }
106
- }
107
-
108
- // Transforming hamburger into x
109
- &.is-selected {
110
- color: var(--theme-topbar-item-color-current);
111
- background-color: var(--theme-topbar-item-background-current);
112
-
113
- span {
114
- background-color: transparent;
115
-
116
- &:before,
117
- &:after {
118
- top: 0;
119
- transform: rotate(-45deg);
120
- }
121
-
122
- &:after { transform: rotate(45deg); }
123
- }
124
- }
125
-
126
- &:hover {
127
- color: var(--theme-topbar-item-color-hover);
128
- background-color: var(--theme-topbar-item-background-hover);
129
- }
130
- }
131
-
132
- .s-navigation {
133
- .s-navigation--item:not(.is-selected) {
134
- color: var(--theme-topbar-item-color);
135
- }
136
-
137
- .s-navigation--item:not(.is-selected):hover {
138
- color: var(--theme-topbar-item-color-hover);
139
- background-color: var(--theme-topbar-item-background-hover);
140
- }
141
- }
142
- }
143
-
144
- // ===========================================================================
145
- // $ LIGHT
146
- // ---------------------------------------------------------------------------
147
- .s-topbar__light {
148
- // TODO this only works 100% perfectly in light mode, due to child elements inheriting current theme colors
149
- // TODO extend forced light mode instead of overriding
150
-
151
- --theme-topbar-background-color: @black-025;
152
-
153
- // Search input
154
- --theme-topbar-search-color: @black-700;
155
- --theme-topbar-search-background: @white;
156
- --theme-topbar-search-placeholder: @black-200;
157
- --theme-topbar-search-border: @black-200;
158
- --theme-topbar-search-border-focus: @blue-300;
159
- --theme-topbar-search-shadow-focus: 0 0 0 @su4 var(--focus-ring);
160
-
161
- // Search switcher
162
- --theme-topbar-select-color: @black-700;
163
- --theme-topbar-select-background: @black-050;
164
-
165
- // Items
166
- --theme-topbar-item-color: @black-600;
167
- --theme-topbar-item-color-hover: @black-800;
168
- --theme-topbar-item-background-hover: @black-075;
169
- --theme-topbar-item-color-current: @black;
170
- --theme-topbar-item-border-current: var(--theme-primary-color);
171
-
172
- // TODO HACK remove everything below once light/dark topbars are inheriting forced themes correctly
173
- // redefine the variables for extra contrast in high-contrast mode
174
- .highcontrast-mode({
175
- // Topbar items
176
- --theme-topbar-item-color: @black-800;
177
- --theme-topbar-item-color-hover: @black-900;
178
- --theme-topbar-item-background-hover: @black-075;
179
- --theme-topbar-item-color-current: @black;
180
- });
181
-
182
- --scrollbar: hsla(0, 0%, 0%, 0.2);
183
- }
184
-
185
- // ===========================================================================
186
- // $ DARK
187
- // ---------------------------------------------------------------------------
188
- .s-topbar__dark {
189
- // TODO this only works 100% perfectly in dark mode, due to child elements inheriting current theme colors
190
- // TODO extend forced dark mode instead of overriding
191
-
192
- @topbar-actual-background: @black-800;
193
- // TODO
194
- #calc-topbar-lightness-increase() when (lightness(@topbar-actual-background) < 15%) {
195
- @topbar-search-lightness-increase: 20%;
196
- }
197
- #calc-topbar-lightness-increase() when not (lightness(@topbar-actual-background) < 15%) {
198
- @topbar-search-lightness-increase: 10%;
199
- }
200
- #calc-topbar-lightness-increase();
201
-
202
- --theme-topbar-background-color: @topbar-actual-background;
203
-
204
- // Search input
205
- --theme-topbar-search-color: lighten(@topbar-actual-background, 80% + @topbar-search-lightness-increase);
206
- --theme-topbar-search-background: lighten(@topbar-actual-background, @topbar-search-lightness-increase);
207
- --theme-topbar-search-placeholder: lighten(@topbar-actual-background, 60% + @topbar-search-lightness-increase);
208
- --theme-topbar-search-border: lighten(@topbar-actual-background, 20% + @topbar-search-lightness-increase);
209
- --theme-topbar-search-border-focus: lighten(@topbar-actual-background, 45% + @topbar-search-lightness-increase);
210
- --theme-topbar-search-shadow-focus: 0 0 0 @su4 fade(@white, 30%);
211
-
212
- // Search switcher
213
- --theme-topbar-select-color: lighten(@topbar-actual-background, 60% + @topbar-search-lightness-increase);
214
- --theme-topbar-select-background: lighten(@topbar-actual-background, 10% + @topbar-search-lightness-increase);
215
-
216
- // Items
217
- --theme-topbar-item-color: @black-025;
218
- --theme-topbar-item-color-hover: @white;
219
- --theme-topbar-item-background-hover: @black-700;
220
- --theme-topbar-item-color-current: @white;
221
- --theme-topbar-item-border-current: var(--theme-primary-color);
222
-
223
- // Themed border accent
224
- --theme-topbar-accent-border: none;
225
-
226
- // TODO HACK remove everything below once light/dark topbars are inheriting forced themes correctly
227
- // redefine the variables for extra contrast in high-contrast mode
228
- .highcontrast-mode({
229
- // Topbar items
230
- --theme-topbar-item-color: @white;
231
- --theme-topbar-item-color-hover: @white;
232
- --theme-topbar-item-background-hover: @black-700;
233
- --theme-topbar-item-color-current: @white;
234
-
235
- .s-badge {
236
- border-color: currentColor;
237
- }
238
- });
239
-
240
- --scrollbar: hsla(0, 0%, 100%, 0.2);
241
- }
242
-
243
- // ===========================================================================
244
- // $ CONTENT & CTAS
245
- // ---------------------------------------------------------------------------
246
- .s-topbar .s-topbar--content,
247
- .s-topbar .s-topbar--ctas {
248
- display: flex;
249
- height: 100%;
250
- .list-reset;
251
-
252
- & > li {
253
- display: inline-flex;
254
- }
255
- }
256
-
257
- .s-topbar .s-topbar--content {
258
- overflow-x: auto; // Allow this content to scroll if it gets too long
259
- @scrollbar-styles(); // Style the scrollbars
260
- margin-left: auto; // Push this section as far to the right as possible
261
-
262
- .s-topbar--item {
263
- color: var(--theme-topbar-item-color);
264
- display: inline-flex;
265
- align-items: center;
266
- padding: 0 (@su12 - @su2);
267
- text-decoration: none;
268
- white-space: nowrap;
269
- position: relative;
270
-
271
- &:hover,
272
- &:focus,
273
- &.is-selected,
274
- &.is-selected:hover,
275
- &.is-selected:focus {
276
- color: var(--theme-topbar-item-color-hover);
277
- background-color: var(--theme-topbar-item-background-hover);
278
- text-decoration: none;
279
- outline: none;
280
-
281
- .s-activity-indicator {
282
- top: calc(50% - 18px);
283
- }
284
- }
285
-
286
- .svg-icon {
287
- vertical-align: text-top;
288
- }
289
-
290
- .s-activity-indicator {
291
- position: absolute;
292
- top: calc(50% - 14px);
293
- right: 2px;
294
- transition: top @te-smooth 0.15s;
295
- }
296
- }
297
- }
298
-
299
- // CTAs: Sign in, Sign up, etc. on the far right
300
- .s-topbar .s-topbar--ctas {
301
- padding-left: @su4;
302
- padding-right: @su8;
303
- overflow-x: auto; // Allow this content to scroll if it gets too long
304
- @scrollbar-styles(); // Style the scrollbars
305
- margin-left: auto; // Push this section as far to the right as possible
306
-
307
- li + li {
308
- margin-left: @su4;
309
- }
310
-
311
- .s-topbar--item {
312
- align-self: center;
313
- padding-top: @su8;
314
- padding-bottom: @su8;
315
- }
316
- }
317
-
318
- // ===========================================================================
319
- // $ NOTICE
320
- // ---------------------------------------------------------------------------
321
- .s-topbar--notice {
322
- &:extend(.s-badge);
323
-
324
- text-transform: uppercase;
325
- font-size: @fs-fine;
326
- font-weight: 700;
327
- margin-left: @su8;
328
- margin-right: @su8;
329
- flex-shrink: 0;
330
-
331
- .badge-styles(transparent, transparent, var(--theme-topbar-item-color));
332
-
333
- &:hover,
334
- &:focus {
335
- .badge-styles(var(--theme-topbar-item-background-hover), var(--theme-topbar-item-background-hover), var(--theme-topbar-item-color-hover));
336
- }
337
-
338
- &.is-unread {
339
- .badge-styles(var(--theme-primary-color), var(--theme-primary-color), var(--white));
340
-
341
- &:hover,
342
- &:focus {
343
- .badge-styles(var(--theme-primary-600), var(--theme-primary-600), var(--white));
344
- }
345
- }
346
- }
347
-
348
- // ===========================================================================
349
- // $ SEARCHBAR
350
- // ---------------------------------------------------------------------------
351
- .s-topbar .s-topbar--searchbar {
352
- @inputLineHeights: @lh-sm; // Ensure the line heights between the elements match up
353
- padding: 0 @su8;
354
- display: flex;
355
- align-items: center;
356
- flex-shrink: 10000; // Force the searchbar to shrink as much as possible if there's no extra space
357
- flex-grow: 1; //...but allow it to grow if there *is* extra space
358
-
359
- .s-topbar--searchbar--input-group {
360
- position: relative;
361
- flex-grow: 1;
362
-
363
- .s-input {
364
- border-color: var(--theme-topbar-search-border);
365
- background-color: var(--theme-topbar-search-background);
366
- box-shadow: var(--theme-topbar-search-shadow);
367
- color: var(--theme-topbar-search-color);
368
- display: block;
369
- line-height: @inputLineHeights;
370
-
371
- &:focus {
372
- border-color: var(--theme-topbar-search-border-focus);
373
- box-shadow: var(--theme-topbar-search-shadow-focus);
374
- }
375
-
376
- &::placeholder {
377
- color: var(--theme-topbar-search-placeholder);
378
- font-style: normal;
379
- }
380
- }
381
-
382
- .s-input-icon {
383
- color: var(--theme-topbar-search-placeholder);
384
- }
385
- }
386
-
387
- .s-select {
388
- .wmx2;
389
-
390
- align-self: stretch;
391
- margin-right: -1px;
392
- color: var(--theme-topbar-select-color);
393
-
394
- &:before,
395
- &:after {
396
- z-index: @zi-active; // Make sure our focus ring is above the search input
397
- }
398
- }
399
-
400
- .s-select > select {
401
- .brr0;
402
- height: 100%;
403
- line-height: @inputLineHeights;
404
-
405
- border-color: var(--theme-topbar-search-border);
406
- background-color: var(--theme-topbar-select-background);
407
- color: var(--theme-topbar-select-color);
408
-
409
- &:focus {
410
- border-color: var(--theme-topbar-search-border-focus);
411
- box-shadow: var(--theme-topbar-search-shadow-focus);
412
- z-index: @zi-selected;
413
- }
414
- }
415
-
416
- // Drop the left border of the search input when it is next to the select
417
- .s-select + .s-topbar--searchbar--input-group > .s-input {
418
- .blr0;
419
- }
420
-
421
- #stacks-internals #screen-sm({
422
- display: none;
423
- position: absolute;
424
- left: 0;
425
- right: 0;
426
- top: 100%;
427
- max-width: 100%;
428
- padding: @su8 @su12;
429
- background: var(--theme-topbar-item-background-hover);
430
-
431
- &.s-topbar--searchbar__open {
432
- display: flex;
433
- max-width: none;
434
- }
435
-
436
- .s-select {
437
- .w25;
438
- }
439
- });
440
- }
1
+ //
2
+ // STACK OVERFLOW
3
+ // TOPBAR
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
+ // ============================================================================
10
+ // $ BASE STYLE
11
+ // ----------------------------------------------------------------------------
12
+ .s-topbar {
13
+ min-width: auto;
14
+ box-shadow: var(--bs-sm);
15
+ width: 100%;
16
+ z-index: @zi-navigation-fixed;
17
+ background-color: var(--theme-topbar-background-color);
18
+ height: var(--theme-topbar-height);
19
+ display: flex;
20
+ border-top: var(--theme-topbar-accent-border);
21
+ position: relative;
22
+ align-items: center;
23
+
24
+ // Redefine the variables for extra contrast in high-contrast mode
25
+ .highcontrast-mode({
26
+ // Search input
27
+ --theme-topbar-search-color: var(--theme-topbar-item-color);
28
+ --theme-topbar-search-background: var(--theme-topbar-background-color);
29
+ --theme-topbar-search-placeholder: var(--theme-topbar-item-color);
30
+ --theme-topbar-search-border: var(--theme-topbar-item-color);
31
+ --theme-topbar-search-border-focus: var(--theme-topbar-item-color);
32
+
33
+ // Search switcher
34
+ --theme-topbar-select-color: var(--theme-topbar-item-color);
35
+ --theme-topbar-select-background: var(--theme-topbar-background-color);
36
+
37
+ // Topbar items
38
+ --theme-topbar-item-color: var(--black-800);
39
+ --theme-topbar-item-color-hover: var(--black-900);
40
+ --theme-topbar-item-background-hover: var(--black-200);
41
+ --theme-topbar-item-color-current: var(--black);
42
+ });
43
+
44
+ .highcontrast-mode({ border-bottom: 1px solid currentColor; });
45
+
46
+ // Wraps the content so the topbar stretches 100% w/ content at some value below that
47
+ .s-topbar--container {
48
+ width: @s-full; // wmx12; Consumers should use atomic classes to override this
49
+ max-width: 100%;
50
+ height: 100%;
51
+ display: flex;
52
+ margin: 0 auto;
53
+ align-items: center;
54
+ }
55
+
56
+ .s-topbar--logo {
57
+ padding: 0 @su8;
58
+ height: 100%;
59
+ display: flex;
60
+ align-items: center;
61
+ background-color: transparent;
62
+ }
63
+
64
+ a.s-topbar--logo:hover {
65
+ background-color: var(--theme-topbar-item-background-hover);
66
+ }
67
+
68
+ a.s-topbar--logo.is-selected {
69
+ background-color: var(--theme-topbar-item-background-hover);
70
+ }
71
+
72
+ .s-topbar--menu-btn {
73
+ display: flex;
74
+ height: 100%;
75
+ padding: 0 @su16;
76
+ flex-shrink: 0;
77
+ align-items: center;
78
+ justify-content: center;
79
+
80
+ // Build a hamburger icon manually using spans instead of using `@Svg` helper so
81
+ // we can more easily animate its content and transform the hamburger into an x
82
+ span {
83
+ &,
84
+ &:before,
85
+ &:after {
86
+ width: @su16;
87
+ height: @su2;
88
+ background-color: var(--theme-topbar-item-color);
89
+ position: relative;
90
+ }
91
+
92
+ &:before,
93
+ &:after {
94
+ position: absolute;
95
+ content: '';
96
+ left: 0;
97
+ top: -5px;
98
+ transition: top, transform;
99
+ transition-duration: 0.1s;
100
+ transition-timing-function: ease-in-out;
101
+ }
102
+
103
+ &:after {
104
+ top: 5px;
105
+ }
106
+ }
107
+
108
+ // Transforming hamburger into x
109
+ &.is-selected {
110
+ color: var(--theme-topbar-item-color-current);
111
+ background-color: var(--theme-topbar-item-background-current);
112
+
113
+ span {
114
+ background-color: transparent;
115
+
116
+ &:before,
117
+ &:after {
118
+ top: 0;
119
+ transform: rotate(-45deg);
120
+ }
121
+
122
+ &:after { transform: rotate(45deg); }
123
+ }
124
+ }
125
+
126
+ &:hover {
127
+ color: var(--theme-topbar-item-color-hover);
128
+ background-color: var(--theme-topbar-item-background-hover);
129
+ }
130
+ }
131
+
132
+ .s-navigation {
133
+ .s-navigation--item:not(.is-selected) {
134
+ color: var(--theme-topbar-item-color);
135
+ }
136
+
137
+ .s-navigation--item:not(.is-selected):hover {
138
+ color: var(--theme-topbar-item-color-hover);
139
+ background-color: var(--theme-topbar-item-background-hover);
140
+ }
141
+ }
142
+ }
143
+
144
+ // ===========================================================================
145
+ // $ LIGHT
146
+ // ---------------------------------------------------------------------------
147
+ .s-topbar__light {
148
+ // TODO this only works 100% perfectly in light mode, due to child elements inheriting current theme colors
149
+ // TODO extend forced light mode instead of overriding
150
+
151
+ --theme-topbar-background-color: @black-025;
152
+
153
+ // Search input
154
+ --theme-topbar-search-color: @black-700;
155
+ --theme-topbar-search-background: @white;
156
+ --theme-topbar-search-placeholder: @black-200;
157
+ --theme-topbar-search-border: @black-200;
158
+ --theme-topbar-search-border-focus: @blue-300;
159
+ --theme-topbar-search-shadow-focus: 0 0 0 @su4 var(--focus-ring);
160
+
161
+ // Search switcher
162
+ --theme-topbar-select-color: @black-700;
163
+ --theme-topbar-select-background: @black-050;
164
+
165
+ // Items
166
+ --theme-topbar-item-color: @black-600;
167
+ --theme-topbar-item-color-hover: @black-800;
168
+ --theme-topbar-item-background-hover: @black-075;
169
+ --theme-topbar-item-color-current: @black;
170
+ --theme-topbar-item-border-current: var(--theme-primary-color);
171
+
172
+ // TODO HACK remove everything below once light/dark topbars are inheriting forced themes correctly
173
+ // redefine the variables for extra contrast in high-contrast mode
174
+ .highcontrast-mode({
175
+ // Topbar items
176
+ --theme-topbar-item-color: @black-800;
177
+ --theme-topbar-item-color-hover: @black-900;
178
+ --theme-topbar-item-background-hover: @black-075;
179
+ --theme-topbar-item-color-current: @black;
180
+ });
181
+
182
+ --scrollbar: hsla(0, 0%, 0%, 0.2);
183
+ }
184
+
185
+ // ===========================================================================
186
+ // $ DARK
187
+ // ---------------------------------------------------------------------------
188
+ .s-topbar__dark {
189
+ // TODO this only works 100% perfectly in dark mode, due to child elements inheriting current theme colors
190
+ // TODO extend forced dark mode instead of overriding
191
+
192
+ @topbar-actual-background: @black-800;
193
+ // TODO
194
+ #calc-topbar-lightness-increase() when (lightness(@topbar-actual-background) < 15%) {
195
+ @topbar-search-lightness-increase: 20%;
196
+ }
197
+ #calc-topbar-lightness-increase() when not (lightness(@topbar-actual-background) < 15%) {
198
+ @topbar-search-lightness-increase: 10%;
199
+ }
200
+ #calc-topbar-lightness-increase();
201
+
202
+ --theme-topbar-background-color: @topbar-actual-background;
203
+
204
+ // Search input
205
+ --theme-topbar-search-color: lighten(@topbar-actual-background, 80% + @topbar-search-lightness-increase);
206
+ --theme-topbar-search-background: lighten(@topbar-actual-background, @topbar-search-lightness-increase);
207
+ --theme-topbar-search-placeholder: lighten(@topbar-actual-background, 60% + @topbar-search-lightness-increase);
208
+ --theme-topbar-search-border: lighten(@topbar-actual-background, 20% + @topbar-search-lightness-increase);
209
+ --theme-topbar-search-border-focus: lighten(@topbar-actual-background, 45% + @topbar-search-lightness-increase);
210
+ --theme-topbar-search-shadow-focus: 0 0 0 @su4 fade(@white, 30%);
211
+
212
+ // Search switcher
213
+ --theme-topbar-select-color: lighten(@topbar-actual-background, 60% + @topbar-search-lightness-increase);
214
+ --theme-topbar-select-background: lighten(@topbar-actual-background, 10% + @topbar-search-lightness-increase);
215
+
216
+ // Items
217
+ --theme-topbar-item-color: @black-100;
218
+ --theme-topbar-item-color-hover: @white;
219
+ --theme-topbar-item-background-hover: @black-700;
220
+ --theme-topbar-item-color-current: @white;
221
+ --theme-topbar-item-border-current: var(--theme-primary-color);
222
+
223
+ // Themed border accent
224
+ --theme-topbar-accent-border: none;
225
+
226
+ // TODO HACK remove everything below once light/dark topbars are inheriting forced themes correctly
227
+ // redefine the variables for extra contrast in high-contrast mode
228
+ .highcontrast-mode({
229
+ // Topbar items
230
+ --theme-topbar-item-color: @white;
231
+ --theme-topbar-item-color-hover: @white;
232
+ --theme-topbar-item-background-hover: @black-700;
233
+ --theme-topbar-item-color-current: @white;
234
+
235
+ .s-badge {
236
+ border-color: currentColor;
237
+ }
238
+ });
239
+
240
+ --scrollbar: hsla(0, 0%, 100%, 0.2);
241
+ }
242
+
243
+ // ===========================================================================
244
+ // $ CONTENT & CTAS
245
+ // ---------------------------------------------------------------------------
246
+ .s-topbar .s-topbar--content {
247
+ display: flex;
248
+ height: 100%;
249
+ .list-reset;
250
+
251
+ & > li {
252
+ display: inline-flex;
253
+ }
254
+
255
+ overflow-x: auto; // Allow this content to scroll if it gets too long
256
+ @scrollbar-styles(); // Style the scrollbars
257
+ margin-left: auto; // Push this section as far to the right as possible
258
+
259
+ .s-topbar--item:not(.s-topbar--item__unset) {
260
+ color: var(--theme-topbar-item-color);
261
+ display: inline-flex;
262
+ align-items: center;
263
+ padding: 0 (@su12 - @su2);
264
+ text-decoration: none;
265
+ white-space: nowrap;
266
+ position: relative;
267
+
268
+ &:hover,
269
+ &:focus,
270
+ &.is-selected,
271
+ &.is-selected:hover,
272
+ &.is-selected:focus {
273
+ color: var(--theme-topbar-item-color-hover);
274
+ background-color: var(--theme-topbar-item-background-hover);
275
+ text-decoration: none;
276
+ outline: none;
277
+
278
+ .s-activity-indicator {
279
+ top: calc(50% - 18px);
280
+ }
281
+ }
282
+
283
+ .svg-icon {
284
+ vertical-align: text-top;
285
+ }
286
+
287
+ .s-activity-indicator {
288
+ position: absolute;
289
+ top: calc(50% - 14px);
290
+ right: 2px;
291
+ transition: top @te-smooth 0.15s;
292
+ }
293
+ }
294
+
295
+ // provide only layout styling for unset items
296
+ .s-topbar--item__unset {
297
+ align-self: center;
298
+ padding-top: @su8;
299
+ padding-bottom: @su8;
300
+ }
301
+ }
302
+
303
+ // ===========================================================================
304
+ // $ NOTICE
305
+ // ---------------------------------------------------------------------------
306
+ .s-topbar--notice {
307
+ &:extend(.s-badge);
308
+
309
+ text-transform: uppercase;
310
+ font-size: @fs-fine;
311
+ font-weight: 700;
312
+ margin-left: @su8;
313
+ margin-right: @su8;
314
+ flex-shrink: 0;
315
+
316
+ .badge-styles(transparent, transparent, var(--theme-topbar-item-color));
317
+
318
+ &:hover,
319
+ &:focus {
320
+ .badge-styles(var(--theme-topbar-item-background-hover), var(--theme-topbar-item-background-hover), var(--theme-topbar-item-color-hover));
321
+ }
322
+
323
+ &.is-unread {
324
+ .badge-styles(var(--theme-primary-color), var(--theme-primary-color), var(--white));
325
+
326
+ &:hover,
327
+ &:focus {
328
+ .badge-styles(var(--theme-primary-600), var(--theme-primary-600), var(--white));
329
+ }
330
+ }
331
+ }
332
+
333
+ // ===========================================================================
334
+ // $ SEARCHBAR
335
+ // ---------------------------------------------------------------------------
336
+ .s-topbar .s-topbar--searchbar {
337
+ @inputLineHeights: @lh-sm; // Ensure the line heights between the elements match up
338
+ padding: 0 @su8;
339
+ display: flex;
340
+ align-items: center;
341
+ flex-shrink: 10000; // Force the searchbar to shrink as much as possible if there's no extra space
342
+ flex-grow: 1; //...but allow it to grow if there *is* extra space
343
+
344
+ .s-topbar--searchbar--input-group {
345
+ position: relative;
346
+ flex-grow: 1;
347
+
348
+ .s-input {
349
+ border-color: var(--theme-topbar-search-border);
350
+ background-color: var(--theme-topbar-search-background);
351
+ box-shadow: var(--theme-topbar-search-shadow);
352
+ color: var(--theme-topbar-search-color);
353
+ display: block;
354
+ line-height: @inputLineHeights;
355
+
356
+ &:focus {
357
+ border-color: var(--theme-topbar-search-border-focus);
358
+ box-shadow: var(--theme-topbar-search-shadow-focus);
359
+ }
360
+
361
+ &::placeholder {
362
+ color: var(--theme-topbar-search-placeholder);
363
+ font-style: normal;
364
+ }
365
+ }
366
+
367
+ .s-input-icon {
368
+ color: var(--theme-topbar-search-placeholder);
369
+ }
370
+ }
371
+
372
+ .s-select {
373
+ .wmx2;
374
+
375
+ align-self: stretch;
376
+ margin-right: -1px;
377
+ color: var(--theme-topbar-select-color);
378
+
379
+ &:before,
380
+ &:after {
381
+ z-index: @zi-active; // Make sure our focus ring is above the search input
382
+ }
383
+ }
384
+
385
+ .s-select > select {
386
+ .brr0;
387
+ height: 100%;
388
+ line-height: @inputLineHeights;
389
+
390
+ border-color: var(--theme-topbar-search-border);
391
+ background-color: var(--theme-topbar-select-background);
392
+ color: var(--theme-topbar-select-color);
393
+
394
+ &:focus {
395
+ border-color: var(--theme-topbar-search-border-focus);
396
+ box-shadow: var(--theme-topbar-search-shadow-focus);
397
+ z-index: @zi-selected;
398
+ }
399
+ }
400
+
401
+ // Drop the left border of the search input when it is next to the select
402
+ .s-select + .s-topbar--searchbar--input-group > .s-input {
403
+ .blr0;
404
+ }
405
+
406
+ #stacks-internals #screen-sm({
407
+ display: none;
408
+ position: absolute;
409
+ left: 0;
410
+ right: 0;
411
+ top: 100%;
412
+ max-width: 100%;
413
+ padding: @su8 @su12;
414
+ background: var(--theme-topbar-item-background-hover);
415
+
416
+ &.s-topbar--searchbar__open {
417
+ display: flex;
418
+ max-width: none;
419
+ }
420
+
421
+ .s-select {
422
+ .w25;
423
+ }
424
+ });
425
+ }