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