@stackoverflow/stacks 1.8.0 → 1.9.1

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