@wwtdev/bsds-css 2.31.0 → 2.33.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.
@@ -1,17 +1,53 @@
1
1
  @mixin vertical-navigation() {
2
2
  :root {
3
- --bs-vertical-nav-width: 9.875rem;
3
+ --bs-vertical-nav-width: 11.25rem;
4
4
  --bs-vertical-nav-narrow-width: 4.5rem;
5
+ --bs-vertical-nav-collapsed-width: 4.5rem;
6
+ /* Dynamic width set by the navigation component for page layout */
7
+ --bs-page-nav-width: 0px;
5
8
  }
6
9
 
7
- .bs-vertical-nav {
10
+ .bs-vertical-nav-wrapper {
8
11
  --active-color: rgba(255, 255, 255, 0.25);
9
12
  --bg-color: var(--bs-navy-base);
10
13
  --border-color: var(--bs-border-dark);
14
+ --text-color: var(--bs-white);
15
+ --link-color: var(--bs-white);
16
+ --link-hover-color: var(--bs-white);
17
+ --link-active-color: var(--bs-white);
18
+ --toggle-bg-color: var(--bg-color);
19
+ --toggle-color: var(--bs-white);
11
20
  --top-offset: 48px;
21
+ }
22
+
23
+ .bs-vertical-nav-wrapper:where([data-bg-variant="bg-base"]) {
24
+ --active-color: var(--bs-blue-10);
25
+ --bg-color: var(--bs-bg-base);
26
+ --border-color: var(--bs-border-medium);
27
+ --text-color: var(--bs-ink-medium);
28
+ --link-color: var(--bs-ink-medium);
29
+ --link-hover-color: var(--bs-ink-blue);
30
+ --link-active-color: var(--bs-ink-blue);
31
+ --toggle-bg-color: var(--bs-bg-base);
32
+ --toggle-color: var(--bs-ink-medium);
33
+ }
34
+
35
+ .dark :where(.bs-vertical-nav-wrapper),
36
+ .dark :where(.bs-vertical-nav-wrapper:where([data-bg-variant="bg-base"])) {
37
+ --active-color: rgba(255, 255, 255, 0.25);
38
+ --bg-color: var(--bs-bg-base);
39
+ --border-color: var(--bs-border-medium);
40
+ --text-color: var(--bs-white);
41
+ --link-color: var(--bs-white);
42
+ --link-hover-color: var(--bs-white);
43
+ --link-active-color: var(--bs-white);
44
+ }
45
+
46
+ .bs-vertical-nav {
12
47
  -ms-overflow-style: none; /* Internet Explorer 10+ */
13
48
  background-color: var(--bg-color);
14
- color: var(--bs-white);
49
+ border-inline-end: 1px solid var(--border-color);
50
+ color: var(--text-color);
15
51
  display: flex;
16
52
  flex-direction: column;
17
53
  height: 100dvh;
@@ -27,61 +63,111 @@
27
63
  right: 0;
28
64
  scrollbar-width: none; /* Firefox */
29
65
  top: var(--top-offset);
30
- /* Slight delay for visibility to change prior to opacity */
31
66
  transition: opacity 200ms ease 10ms;
32
67
  visibility: hidden;
68
+ pointer-events: none;
33
69
  width: auto;
34
- z-index: 1000;
70
+ z-index: 999;
35
71
  }
36
72
 
37
73
  .bs-vertical-nav:where([data-mobile-shown="true"]) {
38
74
  opacity: 1;
39
75
  visibility: visible;
76
+ pointer-events: auto;
40
77
  }
41
78
 
42
- .dark .bs-vertical-nav {
43
- --active-color: rgba(255, 255, 255, 0.25);
44
- --bg-color: var(--bs-bg-base);
45
- --border-color: var(--bs-border-dark);
46
- border-right: 1px solid var(--bs-border-medium);
79
+ .bs-vertical-nav:where([data-collapsible="true"]) {
80
+ transition: opacity 200ms ease 10ms, width 350ms cubic-bezier(0.4, 0, 0.2, 1);
47
81
  }
48
82
 
49
83
  @media (min-width: 1166px) {
50
84
  .bs-vertical-nav {
51
- border-right: 1px solid var(--bg-color);
52
85
  opacity: 1;
53
- padding-bottom: 1rem;
54
- padding-left: 0.5rem;
55
- padding-right: 0.5rem;
56
- padding-top: 1rem;
86
+ padding: 1rem;
57
87
  right: auto;
58
- transition: none;
59
88
  visibility: visible;
89
+ pointer-events: auto;
60
90
  width: var(--bs-vertical-nav-width);
61
91
  }
62
92
 
63
93
  .bs-vertical-nav:where([data-narrow="true"]) {
64
94
  width: var(--bs-vertical-nav-narrow-width);
65
95
  }
96
+
97
+ .bs-vertical-nav:where([data-collapsed="true"]) {
98
+ width: var(--bs-vertical-nav-collapsed-width);
99
+ }
66
100
  }
67
101
 
68
102
  .bs-vertical-nav::-webkit-scrollbar {
69
103
  display: none; /* Safari and Chrome */
70
104
  }
71
105
 
106
+ /* ===== Collapse Toggle Button ===== */
107
+ .bs-vertical-nav-toggle {
108
+ align-items: center;
109
+ background: var(--toggle-bg-color);
110
+ border: 1px solid var(--border-color);
111
+ border-radius: 100px;
112
+ color: var(--toggle-color);
113
+ cursor: pointer;
114
+ display: none; /* Hidden by default on mobile */
115
+ height: 24px;
116
+ width: 24px;
117
+ justify-content: center;
118
+ padding: 0;
119
+ position: fixed;
120
+ left: calc(var(--bs-vertical-nav-width) - 0.5rem);
121
+ pointer-events: auto; /* Ensure button is clickable */
122
+ top: calc(var(--top-offset) + 1.125rem); /* top-offset + 18px */
123
+ transition: left 300ms ease-out, opacity 100ms ease-out;
124
+ z-index: 1002; /* Above nav to prevent hover conflicts */
125
+ }
126
+
127
+ @media (min-width: 1166px) {
128
+ .bs-vertical-nav-toggle {
129
+ display: flex;
130
+ opacity: 1;
131
+ transition: left 300ms ease-out, opacity 100ms ease-out;
132
+ }
133
+
134
+ .bs-vertical-nav-toggle:where([data-collapsed="true"]) {
135
+ left: calc(var(--bs-vertical-nav-collapsed-width) - 0.5rem);
136
+ }
137
+
138
+ /* Adjust position for narrow variant when NOT collapsed */
139
+ .bs-vertical-nav-toggle:where([data-narrow="true"]:not([data-collapsed="true"])) {
140
+ left: calc(var(--bs-vertical-nav-narrow-width) - 0.5rem);
141
+ }
142
+ }
143
+
144
+ .bs-vertical-nav-toggle-icon {
145
+ height: 8px;
146
+ width: 8px;
147
+ color: inherit;
148
+ transition: transform 200ms var(--bs-transition-ease);
149
+ will-change: transform;
150
+ flex-shrink: 0;
151
+ }
152
+
72
153
  /* ===== Sections ===== */
73
154
  .bs-vertical-nav :where(.bs-vertical-nav-section) {
74
- border-top: 2px solid var(--border-color);
155
+ border-top: 1px solid var(--border-color);
75
156
  margin-top: 0.5rem;
76
157
  padding-top: 0.5rem;
77
158
  }
78
159
 
79
160
  @media (min-width: 1166px) {
80
161
  .bs-vertical-nav :where(.bs-vertical-nav-section) {
81
- margin-top: 0.25rem;
162
+ margin-top: 0.5rem;
82
163
  }
83
164
  }
84
165
 
166
+ /* Divider-only sections have no additional padding since no toggle button */
167
+ .bs-vertical-nav :where(.bs-vertical-nav-section[data-divider-only="true"]) {
168
+ padding-top: 0.5rem;
169
+ }
170
+
85
171
  /* Don't show border if the very first item is a section */
86
172
  .bs-vertical-nav :where(ul li:first-child) {
87
173
  border-top: none;
@@ -106,7 +192,7 @@
106
192
  @media (min-width: 1166px) {
107
193
  .bs-vertical-nav :where(.bs-vertical-nav-section-toggle) {
108
194
  /* nav width - nav left padding - nav right padding */
109
- width: calc(var(--bs-vertical-nav-width) - 0.5rem - 0.5rem);
195
+ width: calc(var(--bs-vertical-nav-width) - 1rem - 1rem);
110
196
  }
111
197
 
112
198
  .bs-vertical-nav :where(.bs-vertical-nav-section-toggle span:first-child) {
@@ -114,7 +200,7 @@
114
200
  text-align: start;
115
201
  text-overflow: ellipsis;
116
202
  /* nav width - nav left padding - nav right padding - link left padding - link right padding - caret width */
117
- width: calc(var(--bs-vertical-nav-width) - 0.5rem - 0.5rem - 0.75rem - 0.75rem - 0.75rem);
203
+ width: calc(var(--bs-vertical-nav-width) - 1rem - 1rem - 0.75rem - 0.75rem - 0.75rem);
118
204
  }
119
205
  }
120
206
 
@@ -141,66 +227,72 @@
141
227
  padding-left: 0;
142
228
  }
143
229
 
144
- @media (min-width: 1166px) {
145
- .bs-vertical-nav :where(ul) {
146
- gap: 0.25rem;
147
- }
148
- }
149
-
150
230
  /* ===== Nav List Items / Links */
151
231
  .bs-vertical-nav :where(ul li a) {
152
232
  align-items: center;
153
233
  border-radius: 4px;
234
+ color: var(--link-color);
154
235
  cursor: pointer;
155
236
  display: flex;
156
237
  font-size: 1rem;
157
238
  font-weight: 400;
158
239
  gap: 0.5rem;
159
240
  height: 100%;
160
- padding-bottom: 0.75rem;
161
- padding-left: 0.75rem;
162
- padding-right: 0.75rem;
163
- padding-top: 0.75rem;
164
- width: 100%;
241
+ padding: 0.5rem 0.75rem;
242
+ position: relative;
243
+ }
244
+
245
+ /* Narrow variant - text always visible on desktop (overrides collapsed state) */
246
+ @media (min-width: 1166px) {
247
+ .bs-vertical-nav:where([data-narrow="true"]) :where(ul li a > span:last-child) {
248
+ opacity: 1;
249
+ visibility: visible;
250
+ width: auto;
251
+ }
165
252
  }
166
253
 
167
254
  @media (min-width: 1166px) {
168
255
  .bs-vertical-nav :where(ul li a) {
169
256
  font-size: 0.875rem;
170
- padding-bottom: 0.5rem;
171
- padding-top: 0.5rem;
257
+ min-height: 2.5rem; /* Fixed minimum height to prevent height changes */
258
+ padding: 0.5rem 0.75rem; /* Explicit padding for consistency */
172
259
  /* nav width - nav left padding - nav right padding */
173
- width: calc(var(--bs-vertical-nav-width) - 0.5rem - 0.5rem);
260
+ width: calc(var(--bs-vertical-nav-width) - 1rem - 1rem);
261
+ }
262
+
263
+ /* Collapsed state width */
264
+ .bs-vertical-nav:where([data-collapsed="true"]) :where(ul li a) {
265
+ /* collapsed width - nav left padding - nav right padding */
266
+ width: calc(var(--bs-vertical-nav-collapsed-width) - 1rem - 1rem);
174
267
  }
175
268
 
176
269
  /* Text overflow - normal width - no icon */
177
270
  .bs-vertical-nav :where(ul li a:not(:has(.bs-vertical-nav-link-icon)) span:first-child) {
178
271
  overflow: hidden;
179
272
  text-overflow: ellipsis;
273
+ white-space: nowrap;
180
274
  /* nav width - nav left padding - nav right padding - link left padding - link right padding */
181
- width: calc(var(--bs-vertical-nav-width) - 0.5rem - 0.5rem - 0.75rem - 0.75rem);
275
+ width: calc(var(--bs-vertical-nav-width) - 1rem - 1rem - 0.75rem - 0.75rem);
182
276
  }
183
277
 
184
278
  /* Text overflow - normal width - with icon */
185
279
  .bs-vertical-nav :where(ul li a:has(.bs-vertical-nav-link-icon) span:nth-child(2)) {
186
280
  overflow: hidden;
187
281
  text-overflow: ellipsis;
282
+ white-space: nowrap;
188
283
  /* nav width - nav left padding - nav right padding - link left padding - link right padding - icon width - icon gap */
189
- width: calc(var(--bs-vertical-nav-width) - 0.5rem - 0.5rem - 0.75rem - 0.75rem - 0.875rem - 0.5rem);
284
+ width: calc(var(--bs-vertical-nav-width) - 1rem - 1rem - 0.75rem - 0.75rem - 1rem - 0.5rem);
190
285
  }
191
286
 
192
287
  .bs-vertical-nav:where([data-narrow="true"]) :where(ul li a) {
193
288
  flex-direction: column;
194
289
  font-size: 0.6875rem;
195
- gap: 0.25rem;
290
+ gap: 0.5rem; /* 8px - matches Figma */
196
291
  line-height: 1.3;
197
- padding-bottom: 0.75rem;
198
- padding-left: 0.25rem;
199
- padding-right: 0.25rem;
200
- padding-top: 0.75rem;
292
+ padding: 0.5rem 0.75rem; /* 8px 12px - matches Figma */
201
293
  text-align: center;
202
294
  /* nav width - nav left padding - nav right padding */
203
- width: calc(var(--bs-vertical-nav-narrow-width) - 0.5rem - 0.5rem);
295
+ width: calc(var(--bs-vertical-nav-narrow-width) - 1rem - 1rem);
204
296
  }
205
297
 
206
298
  /* Text overflow - narrow width */
@@ -208,37 +300,159 @@
208
300
  .bs-vertical-nav:where([data-narrow="true"]) :where(ul li a:has(.bs-vertical-nav-link-icon) span:nth-child(2)) {
209
301
  overflow: hidden;
210
302
  text-overflow: ellipsis;
303
+ white-space: nowrap;
211
304
  /* nav width - nav left padding - nav right padding - link left padding */
212
305
  width: calc(var(--bs-vertical-nav-narrow-width) - 0.5rem - 0.5rem);
213
306
  }
214
307
  }
215
308
 
309
+ .bs-vertical-nav-section:where([data-app-links="true"]) {
310
+ padding-top: 1rem;
311
+ }
312
+
313
+ .bs-vertical-nav-section:where([data-app-links="true"]) :where(ul li a) {
314
+ padding: 0.375rem 0.5rem;
315
+ font-size: 0.75rem;
316
+ font-weight: 600;
317
+ }
318
+
216
319
  .bs-vertical-nav :where(ul li a:hover) {
320
+ color: var(--link-hover-color);
217
321
  font-weight: 600;
218
322
  }
219
323
 
324
+ .bs-vertical-nav-section:where([data-app-links="true"]) :where(ul li a:hover) {
325
+ color: var(--bs-ink-blue);
326
+ }
327
+
220
328
  .bs-vertical-nav :where(ul li a[data-active="true"]) {
221
329
  background-color: var(--active-color);
330
+ color: var(--link-active-color);
222
331
  font-weight: 600;
332
+ transition: background-color 200ms ease-out;
223
333
  }
224
334
 
335
+ /* Icon sizing - mobile/default */
225
336
  .bs-vertical-nav :where(.bs-vertical-nav-link-icon) {
226
337
  height: 1rem;
227
338
  width: 1rem;
339
+ flex-shrink: 0; /* Prevent icon from shrinking */
228
340
  }
229
341
 
230
342
  @media (min-width: 1166px) {
231
- .bs-vertical-nav :where(.bs-vertical-nav-link-icon) {
343
+ /* Wide and collapsible variant icons - 14px */
344
+ .bs-vertical-nav:not([data-narrow="true"]) :where(.bs-vertical-nav-link-icon) {
232
345
  height: 0.875rem;
233
346
  width: 0.875rem;
234
347
  }
235
348
 
349
+ /* Narrow variant icons - 16px (inherits from base) */
236
350
  .bs-vertical-nav:where([data-narrow="true"]) :where(.bs-vertical-nav-link-icon) {
237
351
  height: 1rem;
238
352
  width: 1rem;
239
353
  }
240
354
  }
241
355
 
356
+ .bs-vertical-nav-section:where([data-app-links="true"]) .bs-vertical-nav-link-icon {
357
+ height: 1.5rem;
358
+ width: 1.5rem;
359
+ margin-left: 0;
360
+ }
361
+
362
+ /* Default: Show text on mobile */
363
+ .bs-vertical-nav :where(ul li a > span:last-child) {
364
+ opacity: 1;
365
+ visibility: visible;
366
+ width: auto;
367
+ }
368
+
369
+ /* Desktop: Show text when NOT collapsed */
370
+ @media (min-width: 1166px) {
371
+ .bs-vertical-nav:not([data-collapsed="true"]) :where(ul li a > span:last-child) {
372
+ opacity: 1;
373
+ visibility: visible;
374
+ width: auto;
375
+ /* Immediate visibility when appropriate */
376
+ transition: opacity 150ms ease, visibility 0ms linear;
377
+ }
378
+ }
379
+
380
+ /* Desktop: Hide text when collapsed */
381
+ @media (min-width: 1166px) {
382
+ .bs-vertical-nav:where([data-collapsed="true"]) :where(ul li a > span:last-child) {
383
+ opacity: 0;
384
+ visibility: hidden;
385
+ width: 0;
386
+ overflow: hidden;
387
+ white-space: nowrap;
388
+ /* Delay visibility to prevent flash during breakpoint transition */
389
+ transition: opacity 150ms ease, visibility 0ms linear 150ms;
390
+ }
391
+ }
392
+
393
+ /* Keep icons visible when collapsed */
394
+ .bs-vertical-nav:where([data-collapsed="true"]) :where(.bs-vertical-nav-link-icon) {
395
+ display: block;
396
+ }
397
+
398
+ /* Hide section toggle when collapsed */
399
+ .bs-vertical-nav:where([data-collapsed="true"]) :where(.bs-vertical-nav-section-toggle) {
400
+ display: none;
401
+ }
402
+
403
+ /* ===== Hover Expansion (CSS-only) ===== */
404
+ @media (min-width: 1166px) {
405
+ /* Expand nav on hover when collapsed and collapsible - but NOT when hovering the toggle button */
406
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav[data-collapsed="true"][data-collapsible="true"]) {
407
+ width: var(--bs-vertical-nav-width);
408
+ }
409
+
410
+ /* Narrow variant should respect narrow width on hover */
411
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav[data-collapsed="true"][data-narrow="true"]) {
412
+ width: var(--bs-vertical-nav-narrow-width);
413
+ }
414
+
415
+ /* Expand link widths on hover when collapsed */
416
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav[data-collapsed="true"]) :where(ul li a) {
417
+ width: calc(var(--bs-vertical-nav-width) - 1rem - 1rem);
418
+ }
419
+
420
+ /* Narrow variant links should respect narrow width on hover */
421
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav[data-collapsed="true"][data-narrow="true"]) :where(ul li a) {
422
+ width: calc(var(--bs-vertical-nav-narrow-width) - 0.5rem - 0.5rem);
423
+ }
424
+
425
+ /* Show text on hover when collapsed */
426
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav[data-collapsed="true"]) :where(ul li a > span:last-child) {
427
+ opacity: 1;
428
+ visibility: visible;
429
+ width: auto;
430
+ }
431
+
432
+ /* Hide toggle button on hover when collapsed - but NOT when hovering the button itself */
433
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav-toggle[data-collapsed="true"]) {
434
+ opacity: 0;
435
+ pointer-events: none; /* Prevent interaction when hidden */
436
+ }
437
+
438
+ /* Show section toggles on hover when collapsed */
439
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav[data-collapsed="true"]) :where(.bs-vertical-nav-section-toggle) {
440
+ display: flex;
441
+ }
442
+ }
443
+
444
+ /* ===== Top Content ===== */
445
+ .bs-vertical-nav :where(.bs-vertical-nav-top-content) {
446
+ margin-bottom: 0.5rem;
447
+ padding: 0;
448
+ }
449
+
450
+ @media (min-width: 1166px) {
451
+ .bs-vertical-nav :where(.bs-vertical-nav-top-content) {
452
+ margin-bottom: 0.75rem;
453
+ }
454
+ }
455
+
242
456
  /* ===== End Items ===== */
243
457
  .bs-vertical-nav :where(.bs-vertical-nav-end-items) {
244
458
  display: flex;
@@ -247,12 +461,25 @@
247
461
  margin-top: auto;
248
462
  }
249
463
 
464
+ /* End items visibility for collapsible variant (desktop only) */
465
+ @media (min-width: 1166px) {
466
+ /* Hide end items when collapsible variant is collapsed */
467
+ .bs-vertical-nav:where([data-collapsible="true"][data-collapsed="true"]) :where(.bs-vertical-nav-end-items) {
468
+ display: none;
469
+ }
470
+
471
+ /* Show end items on hover when collapsible variant is collapsed */
472
+ .bs-vertical-nav-wrapper:where(:hover:not(:has(.bs-vertical-nav-toggle:hover))) :where(.bs-vertical-nav[data-collapsible="true"][data-collapsed="true"]) :where(.bs-vertical-nav-end-items) {
473
+ display: flex;
474
+ }
475
+ }
476
+
250
477
  .bs-vertical-nav :where(.bs-vertical-nav-end-items > *) {
251
- color: var(--bs-white);
478
+ color: var(--text-color);
252
479
  }
253
480
 
254
481
  .bs-vertical-nav :where(.bs-vertical-nav-end-items > *:not(button)) {
255
- color: var(--bs-white);
482
+ color: var(--text-color);
256
483
  padding-bottom: 0.5rem;
257
484
  padding-left: 0.75rem;
258
485
  padding-right: 0.75rem;
@@ -272,9 +499,17 @@
272
499
  margin-top: 0.5rem;
273
500
  }
274
501
 
502
+ /* Hide end items in narrow variant (all screen sizes) */
275
503
  .bs-vertical-nav:where([data-narrow="true"]) :where(.bs-vertical-nav-end-items) {
276
504
  display: none;
277
505
  }
278
506
 
507
+ /* ===== CSS-Only Page Layout Support ===== */
508
+ /* Apply to any element that needs to adjust for navigation width (e.g., headers, main content) */
509
+ .bs-header-with-nav {
510
+ margin-inline-start: var(--bs-page-nav-width);
511
+ transition: margin-inline-start 350ms cubic-bezier(0.4, 0, 0.2, 1);
512
+ }
513
+
279
514
  }
280
515