@ngb-bootstrap/core 0.0.0 → 0.1.0-next.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 (76) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +18 -0
  3. package/README.md +26 -0
  4. package/fesm2022/ngb-bootstrap-core-alert.mjs +154 -0
  5. package/fesm2022/ngb-bootstrap-core-alert.mjs.map +1 -0
  6. package/fesm2022/ngb-bootstrap-core-badge.mjs +100 -0
  7. package/fesm2022/ngb-bootstrap-core-badge.mjs.map +1 -0
  8. package/fesm2022/ngb-bootstrap-core-breadcrumb.mjs +135 -0
  9. package/fesm2022/ngb-bootstrap-core-breadcrumb.mjs.map +1 -0
  10. package/fesm2022/ngb-bootstrap-core-button.mjs +513 -0
  11. package/fesm2022/ngb-bootstrap-core-button.mjs.map +1 -0
  12. package/fesm2022/ngb-bootstrap-core-card.mjs +540 -0
  13. package/fesm2022/ngb-bootstrap-core-card.mjs.map +1 -0
  14. package/fesm2022/ngb-bootstrap-core-cdk.mjs +282 -0
  15. package/fesm2022/ngb-bootstrap-core-cdk.mjs.map +1 -0
  16. package/fesm2022/ngb-bootstrap-core-checkbox.mjs +165 -0
  17. package/fesm2022/ngb-bootstrap-core-checkbox.mjs.map +1 -0
  18. package/fesm2022/ngb-bootstrap-core-chips.mjs +512 -0
  19. package/fesm2022/ngb-bootstrap-core-chips.mjs.map +1 -0
  20. package/fesm2022/ngb-bootstrap-core-floating-label.mjs +83 -0
  21. package/fesm2022/ngb-bootstrap-core-floating-label.mjs.map +1 -0
  22. package/fesm2022/ngb-bootstrap-core-footer.mjs +48 -0
  23. package/fesm2022/ngb-bootstrap-core-footer.mjs.map +1 -0
  24. package/fesm2022/ngb-bootstrap-core-icon.mjs +243 -0
  25. package/fesm2022/ngb-bootstrap-core-icon.mjs.map +1 -0
  26. package/fesm2022/ngb-bootstrap-core-input.mjs +540 -0
  27. package/fesm2022/ngb-bootstrap-core-input.mjs.map +1 -0
  28. package/fesm2022/ngb-bootstrap-core-layout.mjs +272 -0
  29. package/fesm2022/ngb-bootstrap-core-layout.mjs.map +1 -0
  30. package/fesm2022/ngb-bootstrap-core-navbar.mjs +150 -0
  31. package/fesm2022/ngb-bootstrap-core-navbar.mjs.map +1 -0
  32. package/fesm2022/ngb-bootstrap-core-radio.mjs +279 -0
  33. package/fesm2022/ngb-bootstrap-core-radio.mjs.map +1 -0
  34. package/fesm2022/ngb-bootstrap-core-sidebar.mjs +425 -0
  35. package/fesm2022/ngb-bootstrap-core-sidebar.mjs.map +1 -0
  36. package/fesm2022/ngb-bootstrap-core-spinner.mjs +126 -0
  37. package/fesm2022/ngb-bootstrap-core-spinner.mjs.map +1 -0
  38. package/fesm2022/ngb-bootstrap-core-switch.mjs +147 -0
  39. package/fesm2022/ngb-bootstrap-core-switch.mjs.map +1 -0
  40. package/fesm2022/ngb-bootstrap-core.mjs +69 -0
  41. package/fesm2022/ngb-bootstrap-core.mjs.map +1 -0
  42. package/ngb-bootstrap.css +827 -0
  43. package/package.json +118 -4
  44. package/styles/_breadcrumb.scss +9 -0
  45. package/styles/_button.scss +14 -0
  46. package/styles/_card.scss +86 -0
  47. package/styles/_chip.scss +10 -0
  48. package/styles/_choice.scss +14 -0
  49. package/styles/_contrast.scss +23 -0
  50. package/styles/_icon.scss +62 -0
  51. package/styles/_index.scss +33 -0
  52. package/styles/_input.scss +9 -0
  53. package/styles/_layout.scss +602 -0
  54. package/styles/_overlay.scss +14 -0
  55. package/styles/_tokens.scss +29 -0
  56. package/styles/_typography.scss +77 -0
  57. package/styles/ngb-bootstrap.scss +2 -0
  58. package/types/ngb-bootstrap-core-alert.d.ts +65 -0
  59. package/types/ngb-bootstrap-core-badge.d.ts +38 -0
  60. package/types/ngb-bootstrap-core-breadcrumb.d.ts +32 -0
  61. package/types/ngb-bootstrap-core-button.d.ts +177 -0
  62. package/types/ngb-bootstrap-core-card.d.ts +154 -0
  63. package/types/ngb-bootstrap-core-cdk.d.ts +165 -0
  64. package/types/ngb-bootstrap-core-checkbox.d.ts +53 -0
  65. package/types/ngb-bootstrap-core-chips.d.ts +170 -0
  66. package/types/ngb-bootstrap-core-floating-label.d.ts +22 -0
  67. package/types/ngb-bootstrap-core-footer.d.ts +16 -0
  68. package/types/ngb-bootstrap-core-icon.d.ts +99 -0
  69. package/types/ngb-bootstrap-core-input.d.ts +208 -0
  70. package/types/ngb-bootstrap-core-layout.d.ts +102 -0
  71. package/types/ngb-bootstrap-core-navbar.d.ts +33 -0
  72. package/types/ngb-bootstrap-core-radio.d.ts +96 -0
  73. package/types/ngb-bootstrap-core-sidebar.d.ts +62 -0
  74. package/types/ngb-bootstrap-core-spinner.d.ts +49 -0
  75. package/types/ngb-bootstrap-core-switch.d.ts +44 -0
  76. package/types/ngb-bootstrap-core.d.ts +82 -0
@@ -0,0 +1,602 @@
1
+ // <ngb-layout>, <ngb-layout-content>, <ngb-navbar>, <ngb-sidebar>, <ngb-footer>.
2
+ // The Taiga UI docs layout on the Bootstrap grid: a fixed header, a rounded window frame drawn by a
3
+ // fixed overlay (so the page keeps native scrolling), a sidebar column and a content column.
4
+ // Mobile and tablet first: below lg the sidebar is a Bootstrap drawer opened from the header.
5
+ // Options (classes set by <ngb-layout>): .ngb-layout-square drops the rounding, .ngb-layout-full-sidebar
6
+ // runs the sidebar the full height beside the navbar, and .ngb-layout-sidebar-collapsed contracts
7
+ // the sidebar to a rail of top-level icons.
8
+
9
+ $lg: 1024px; // Bootstrap 6 --breakpoint-lg
10
+ $md: 768px; // Bootstrap 6 --breakpoint-md
11
+ $ease: 0.3s cubic-bezier(0.2, 0, 0.4, 0.9);
12
+ // The layout's own navbar and sidebar. Option selectors use these child paths so that a layout
13
+ // nested in another (as in the docs' framed demos) isn't styled by the outer one's options.
14
+ $navbar: '> .ngb-navbar';
15
+ $sidebar: '> .container-fluid > .row > .ngb-sidebar';
16
+ $content: '> .container-fluid > .row > .ngb-layout-content';
17
+
18
+ @layer components {
19
+ // Layout -------------------------------------------------------------------------------------
20
+
21
+ .ngb-layout {
22
+ // The sidebar column's current width: full, or the rail when collapsed.
23
+ --ngb-layout-sidebar-size: var(--ngb-sidebar-width);
24
+ // The corner radii in use: the tokens, or 0 when square. Set here rather than overriding the
25
+ // tokens, so a layout nested in a square one (as in the docs' demos) keeps its own rounding.
26
+ --ngb-layout-frame-corner: var(--ngb-layout-frame-radius);
27
+ --ngb-layout-seam-corner: var(--ngb-layout-seam-radius);
28
+
29
+ display: block;
30
+ min-height: 100dvh;
31
+ padding-top: var(--ngb-navbar-height);
32
+ background-color: var(--ngb-layout-panel-bg);
33
+
34
+ // The window frame: an 8px band in the frame colour with rounded inner corners, fixed over the
35
+ // page. The side shadows paint the frame colour past the viewport edges.
36
+ &::before {
37
+ position: fixed;
38
+ inset: calc(var(--ngb-navbar-height) - var(--ngb-layout-frame-width)) 0 0;
39
+ z-index: 1030;
40
+ pointer-events: none;
41
+ content: '';
42
+ border: var(--ngb-layout-frame-width) solid var(--ngb-layout-frame-bg);
43
+ border-radius: var(--ngb-layout-frame-corner);
44
+ box-shadow:
45
+ -5rem 0 0 var(--ngb-layout-frame-bg),
46
+ 5rem 0 0 var(--ngb-layout-frame-bg);
47
+ }
48
+
49
+ @media (width >= $md) {
50
+ --ngb-layout-content-padding: 2rem;
51
+ --ngb-navbar-padding-x: 1.5rem;
52
+ }
53
+
54
+ @media (width >= $lg) {
55
+ --ngb-layout-content-padding: 3rem;
56
+ }
57
+ }
58
+
59
+ .ngb-layout-square {
60
+ --ngb-layout-frame-corner: 0;
61
+ --ngb-layout-seam-corner: 0;
62
+ }
63
+
64
+ @media (width >= $lg) {
65
+ .ngb-layout-sidebar-collapsed {
66
+ --ngb-layout-sidebar-size: var(--ngb-sidebar-collapsed-width);
67
+ }
68
+
69
+ // Full-height sidebar: no frame. The sidebar and the content run to the viewport's edges, with
70
+ // only the seam between them (which also rounds the content's corner below the navbar).
71
+ .ngb-layout-full-sidebar {
72
+ &::before {
73
+ content: none;
74
+ }
75
+
76
+ #{$navbar} {
77
+ inset-inline-start: var(--ngb-layout-sidebar-size);
78
+ transition: inset-inline-start $ease;
79
+ }
80
+
81
+ #{$sidebar} {
82
+ inset-block-start: 0;
83
+
84
+ // Only the seam on the content side; round the content's corner below the navbar.
85
+ &::before {
86
+ inset-block: 0;
87
+ border-width: 0;
88
+ border-inline-end-width: var(--ngb-layout-seam-width);
89
+ border-radius: 0;
90
+ }
91
+
92
+ &::after {
93
+ top: calc(var(--ngb-navbar-height) - var(--ngb-layout-seam-width));
94
+ bottom: calc(var(--ngb-layout-seam-width) * -1);
95
+ }
96
+ }
97
+
98
+ #{$content} {
99
+ padding-inline-end: 0;
100
+
101
+ > .ngb-footer {
102
+ margin-bottom: 0;
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ @media (width >= $lg) and (prefers-reduced-motion: reduce) {
109
+ .ngb-layout-full-sidebar #{$navbar} {
110
+ transition: none;
111
+ }
112
+ }
113
+
114
+ // Overscroll and the area behind the frame show the frame colour.
115
+ :root:has(.ngb-layout) {
116
+ background-color: var(--ngb-layout-frame-bg);
117
+ }
118
+
119
+ // The column shows the frame colour; <main> and the footer are panels on it, separated by a
120
+ // straight 4px gap, the same width as the seam between the sidebar and the content.
121
+ .ngb-layout-content {
122
+ display: flex;
123
+ flex-direction: column;
124
+ row-gap: var(--ngb-layout-seam-width);
125
+ min-width: 0;
126
+ min-height: calc(100dvh - var(--ngb-navbar-height));
127
+ padding-inline: var(--ngb-layout-frame-width);
128
+ background-color: var(--ngb-layout-frame-bg);
129
+
130
+ @media (width >= $lg) {
131
+ padding-inline-start: 0;
132
+ }
133
+ }
134
+
135
+ .ngb-layout-main {
136
+ flex-grow: 1;
137
+ padding: var(--ngb-layout-content-padding);
138
+ background-color: var(--ngb-layout-panel-bg);
139
+ }
140
+
141
+ // Navbar -------------------------------------------------------------------------------------
142
+
143
+ .ngb-navbar {
144
+ --navbar-min-height: var(--ngb-navbar-height);
145
+ --navbar-padding-x: var(--ngb-navbar-padding-x);
146
+ --navbar-padding-y: 0;
147
+ --navbar-bg: var(--ngb-layout-frame-bg);
148
+
149
+ position: fixed;
150
+ inset: 0 0 auto;
151
+ z-index: 1031;
152
+ flex-wrap: nowrap;
153
+ gap: 0.75rem;
154
+ height: var(--ngb-navbar-height);
155
+ font-size: var(--font-size-sm);
156
+ }
157
+
158
+ .ngb-navbar-start,
159
+ .ngb-navbar-end,
160
+ .ngb-navbar-brand,
161
+ .ngb-sidebar-brand {
162
+ display: flex;
163
+ gap: 0.75rem;
164
+ align-items: center;
165
+ min-width: 0;
166
+ }
167
+
168
+ .ngb-navbar-start {
169
+ flex: 1 1 0;
170
+ }
171
+
172
+ .ngb-navbar-end {
173
+ flex: 1 1 0;
174
+ justify-content: flex-end;
175
+ }
176
+
177
+ .ngb-navbar-center {
178
+ display: flex;
179
+ flex: 0 1 auto;
180
+ justify-content: center;
181
+ min-width: 0;
182
+
183
+ &:empty {
184
+ display: none;
185
+ }
186
+
187
+ // Below lg the centre slot (e.g. search) moves to the end, after the actions.
188
+ @media (width < $lg) {
189
+ order: 2;
190
+ }
191
+ }
192
+
193
+ @media (width < $lg) {
194
+ .ngb-navbar-end {
195
+ flex: 0 0 auto;
196
+ order: 1;
197
+ }
198
+ }
199
+
200
+ .ngb-navbar-menu {
201
+ --btn-color: currentcolor;
202
+ --btn-hover-bg: var(--ngb-layout-divider-color);
203
+
204
+ flex-shrink: 0;
205
+ margin-inline-start: -0.5rem;
206
+
207
+ // From lg up the sidebar is a column: the button only contracts and expands a collapsible one.
208
+ @media (width >= $lg) {
209
+ .ngb-layout:not(.ngb-layout-collapsible) #{$navbar} & {
210
+ display: none;
211
+ }
212
+ }
213
+ }
214
+
215
+ // Sidebar ------------------------------------------------------------------------------------
216
+
217
+ .ngb-sidebar {
218
+ // Below lg the sidebar is only the drawer, which is fixed: keep it out of the grid row.
219
+ display: contents;
220
+
221
+ // From lg up it is fixed, as on taiga-ui.dev: it never scrolls with the page, and its seam
222
+ // (which runs under the content) can't widen the page, because fixed boxes add no scroll
223
+ // overflow. The content column is offset by the sidebar width instead.
224
+ @media (width >= $lg) {
225
+ position: fixed;
226
+ inset-block: var(--ngb-navbar-height) 0;
227
+ inset-inline-start: 0;
228
+ z-index: 1;
229
+ display: block;
230
+ width: var(--ngb-layout-sidebar-size);
231
+ background-color: var(--ngb-layout-panel-bg);
232
+ transition: width $ease;
233
+
234
+ & ~ .ngb-layout-content {
235
+ margin-inline-start: var(--ngb-layout-sidebar-size);
236
+ transition: margin-inline-start $ease;
237
+ }
238
+
239
+ // Rounded seam around the sidebar and along the content's leading edge (Taiga's 4px band).
240
+ &::before,
241
+ &::after {
242
+ position: absolute;
243
+ top: calc(var(--ngb-layout-seam-width) * -1);
244
+ bottom: var(--ngb-layout-seam-width);
245
+ pointer-events: none;
246
+ content: '';
247
+ border: var(--ngb-layout-seam-width) solid var(--ngb-layout-frame-bg);
248
+ border-radius: var(--ngb-layout-seam-corner);
249
+ }
250
+
251
+ &::before {
252
+ inset-inline: 0;
253
+ }
254
+
255
+ &::after {
256
+ inset-inline-start: 100%;
257
+ width: 100vw;
258
+ margin-inline-start: calc(var(--ngb-layout-seam-width) * -1);
259
+ }
260
+ }
261
+ }
262
+
263
+ // The brand goes to the top of a full-height sidebar, in a box in the frame colour (rounded like
264
+ // the seam, so square in a square layout), except on the rail, which is too narrow: there it
265
+ // stays in the navbar.
266
+ .ngb-sidebar-brand {
267
+ display: none;
268
+ }
269
+
270
+ @media (width >= $lg) {
271
+ .ngb-layout-full-sidebar:not(.ngb-layout-sidebar-collapsed) {
272
+ #{$navbar} .ngb-navbar-brand {
273
+ display: none;
274
+ }
275
+
276
+ #{$sidebar} .ngb-sidebar-brand {
277
+ display: flex;
278
+ flex: none;
279
+ gap: 0.5rem;
280
+ height: var(--ngb-navbar-height);
281
+ padding-inline: 0.5rem;
282
+ // The same m-3 gap on the top and both sides; the end side also clears the 4px seam.
283
+ margin: var(--spacer-3);
284
+ margin-block-end: 0;
285
+ margin-inline-end: calc(var(--spacer-3) + var(--ngb-layout-seam-width));
286
+ overflow: hidden;
287
+ background-color: var(--ngb-sidebar-brand-bg);
288
+ border-radius: var(--ngb-layout-seam-corner);
289
+ font-size: var(--font-size-sm);
290
+ }
291
+ }
292
+ }
293
+
294
+ .ngb-sidebar-nav {
295
+ padding-block: 0.75rem;
296
+
297
+ // Taiga's drawer has no 4px seam, so its items sit 4px closer to the edge.
298
+ @media (width < $lg) {
299
+ margin-inline-start: -0.25rem;
300
+ }
301
+
302
+ // While a collapsible sidebar expands, keep the items at full width so they are revealed by the
303
+ // growing column instead of rewrapping.
304
+ @media (width >= $lg) {
305
+ .ngb-layout-collapsible #{$sidebar} & {
306
+ width: var(--ngb-sidebar-width);
307
+ }
308
+ }
309
+ }
310
+
311
+ @media (prefers-reduced-motion: reduce) {
312
+ .ngb-sidebar,
313
+ .ngb-sidebar ~ .ngb-layout-content {
314
+ transition: none;
315
+ }
316
+ }
317
+
318
+ // The rail: top-level icons only. Labels stay for screen readers; groups expand the sidebar.
319
+ @media (width >= $lg) {
320
+ .ngb-layout-sidebar-collapsed #{$sidebar} {
321
+ .ngb-sidebar-nav {
322
+ width: auto;
323
+
324
+ // Content placed above the items (e.g. a notice) doesn't fit the rail.
325
+ > :not(.ngb-sidebar-list) {
326
+ display: none;
327
+ }
328
+ }
329
+
330
+ .ngb-sidebar-label {
331
+ position: absolute;
332
+ width: 1px;
333
+ height: 1px;
334
+ overflow: hidden;
335
+ white-space: nowrap;
336
+ clip-path: inset(50%);
337
+ }
338
+
339
+ .ngb-sidebar-icon {
340
+ margin-inline-end: 0;
341
+ }
342
+
343
+ .ngb-sidebar-chevron,
344
+ .ngb-sidebar-collapse {
345
+ display: none;
346
+ }
347
+ }
348
+ }
349
+
350
+ .ngb-sidebar-close:not(:focus-visible) {
351
+ position: absolute !important;
352
+ width: 1px !important;
353
+ height: 1px !important;
354
+ overflow: hidden !important;
355
+ clip-path: inset(50%) !important;
356
+ }
357
+
358
+ .ngb-sidebar-close:focus-visible {
359
+ position: absolute;
360
+ inset-block-start: 0.75rem;
361
+ inset-inline-end: 0.75rem;
362
+ z-index: 1;
363
+ }
364
+
365
+ // From lg up the sidebar is a column, not a drawer: nothing to close.
366
+ @media (width >= $lg) {
367
+ .ngb-sidebar-close {
368
+ display: none;
369
+ }
370
+ }
371
+
372
+ .ngb-sidebar-list {
373
+ padding: 0;
374
+ margin: 0;
375
+ list-style: none;
376
+ }
377
+
378
+ .ngb-sidebar-link {
379
+ --ngb-sidebar-text-x: 3.5625rem;
380
+ --ngb-sidebar-line-x: 2.125rem;
381
+
382
+ position: relative;
383
+ display: flex;
384
+ gap: 0.25rem;
385
+ align-items: center;
386
+ width: 100%;
387
+ min-height: 2.25rem;
388
+ padding: 0.5rem 1rem 0.5rem var(--ngb-sidebar-text-x);
389
+ font: inherit;
390
+ font-size: var(--font-size-sm);
391
+ line-height: 1.25rem;
392
+ color: var(--fg-2);
393
+ text-align: start;
394
+ text-decoration: none;
395
+ cursor: pointer;
396
+ background: none;
397
+ border: 0;
398
+ border-radius: var(--radius-1);
399
+ transition: color 0.3s cubic-bezier(0.2, 0, 0.4, 0.9);
400
+
401
+ &:hover,
402
+ &:focus-visible {
403
+ color: var(--fg-body);
404
+ }
405
+
406
+ &:focus-visible {
407
+ outline: var(--focus-ring);
408
+ outline-offset: -2px;
409
+ }
410
+
411
+ // Tree guide line for nested items.
412
+ &::before {
413
+ position: absolute;
414
+ inset-block: 0;
415
+ inset-inline-start: var(--ngb-sidebar-line-x);
416
+ width: 1px;
417
+ content: '';
418
+ background-color: var(--ngb-layout-divider-color);
419
+ }
420
+
421
+ &.active {
422
+ font-weight: var(--font-weight-bold);
423
+ color: var(--fg-body);
424
+
425
+ // Active marker on the guide line.
426
+ &::after {
427
+ position: absolute;
428
+ inset-block: 0.5rem;
429
+ inset-inline-start: calc(var(--ngb-sidebar-line-x) - 1px);
430
+ width: 3px;
431
+ content: '';
432
+ background-color: currentcolor;
433
+ border-radius: 1rem;
434
+ }
435
+ }
436
+
437
+ &[data-level='2'] {
438
+ --ngb-sidebar-text-x: 4.75rem;
439
+ --ngb-sidebar-line-x: 3.75rem;
440
+ }
441
+
442
+ &[data-level='3'] {
443
+ --ngb-sidebar-text-x: 6.375rem;
444
+ --ngb-sidebar-line-x: 5.375rem;
445
+ }
446
+
447
+ // Top level: bold, with an icon, no guide line.
448
+ &[data-level='0'] {
449
+ gap: 0;
450
+ min-height: 2.5rem;
451
+ padding-block: 0.625rem;
452
+ padding-inline-start: 1.6875rem;
453
+ margin-bottom: -1px;
454
+ font-weight: var(--font-weight-bold);
455
+ color: var(--fg-body);
456
+
457
+ &::before,
458
+ &::after {
459
+ display: none;
460
+ }
461
+ }
462
+ }
463
+
464
+ .ngb-sidebar-icon {
465
+ margin-inline-end: 0.875rem;
466
+ }
467
+
468
+ // A group's children slide open (0fr to 1fr rows animates to the content's height) and fade in,
469
+ // with the chevron's timing.
470
+ .ngb-sidebar-collapse {
471
+ display: grid;
472
+ grid-template-rows: 0fr;
473
+ transition: grid-template-rows 0.3s cubic-bezier(0.2, 0, 0.4, 0.9);
474
+ }
475
+
476
+ .ngb-sidebar-collapse-inner {
477
+ min-height: 0;
478
+ overflow: hidden;
479
+ opacity: 0;
480
+ transition: opacity 0.3s cubic-bezier(0.2, 0, 0.4, 0.9);
481
+ }
482
+
483
+ .ngb-sidebar-collapse-open {
484
+ grid-template-rows: 1fr;
485
+
486
+ > .ngb-sidebar-collapse-inner {
487
+ opacity: 1;
488
+ }
489
+ }
490
+
491
+ @media (prefers-reduced-motion: reduce) {
492
+ .ngb-sidebar-collapse,
493
+ .ngb-sidebar-collapse-inner,
494
+ .ngb-sidebar-chevron {
495
+ transition: none;
496
+ }
497
+ }
498
+
499
+ // Every group's chevron sits at the inline end of its row, aligned down the sidebar.
500
+ .ngb-sidebar-chevron {
501
+ flex-shrink: 0;
502
+ margin-inline-start: auto;
503
+ transition: transform 0.3s cubic-bezier(0.2, 0, 0.4, 0.9);
504
+
505
+ // Collapsed it points to the inline end (mirrored in RTL by <ngb-icon>); expanded it points down.
506
+ [aria-expanded='true'] > & {
507
+ transform: rotate(90deg);
508
+ }
509
+ }
510
+
511
+ // Footer -------------------------------------------------------------------------------------
512
+
513
+ .ngb-footer {
514
+ display: flex;
515
+ flex-wrap: wrap;
516
+ gap: 0.5rem 1.5rem;
517
+ align-items: center;
518
+ justify-content: space-between;
519
+ padding: 1.5rem var(--ngb-layout-content-padding);
520
+ font-size: var(--font-size-sm);
521
+ line-height: 1.25rem;
522
+ color: var(--fg-2);
523
+ border-top: 1px solid var(--ngb-layout-divider-color);
524
+
525
+ // Inside <ngb-layout-content> the footer is its own panel below the seam, not a divided strip.
526
+ // The frame covers the bottom 8px, so keep it clear of that.
527
+ .ngb-layout-content > & {
528
+ margin-bottom: var(--ngb-layout-frame-width);
529
+ background-color: var(--ngb-layout-panel-bg);
530
+ border-top: 0;
531
+ }
532
+
533
+ a {
534
+ color: inherit;
535
+ text-decoration: none;
536
+
537
+ &:hover {
538
+ color: var(--fg-body);
539
+ }
540
+ }
541
+ }
542
+ }
543
+
544
+ // Unlayered on purpose: Bootstrap 6 declares its drawer tokens outside any cascade layer, so these
545
+ // overrides must be too. Same specificity as .lg\:drawer and loaded later, so they win.
546
+ // Below lg: a full-height panel flush with the start edge over a plain dark backdrop, like
547
+ // taiga-ui.dev's mobile menu.
548
+ .ngb-sidebar-drawer {
549
+ --drawer-width: min(17.25rem, calc(100vw - 3rem));
550
+ // With a unit: Bootstrap slides the drawer off screen with calc(-100% - var(--drawer-inset)),
551
+ // which a unitless 0 makes invalid, leaving the drawer in place with no animation.
552
+ --drawer-inset: 0px;
553
+ --drawer-border-width: 0;
554
+ --drawer-border-radius: 0;
555
+ --drawer-box-shadow: none;
556
+ --drawer-bg: var(--ngb-layout-panel-bg);
557
+ --drawer-backdrop-bg: rgb(0 0 0 / 50%);
558
+ --drawer-backdrop-blur: 0;
559
+
560
+ .drawer-body {
561
+ padding: 0;
562
+ }
563
+
564
+ // Below lg it slides in and out. `overlay` keeps a closing drawer in the top layer (above the
565
+ // fixed navbar) until it has slid away, and its backdrop fades out alongside.
566
+ @media (width < $lg) {
567
+ --drawer-transition-property: transform, visibility, overlay;
568
+
569
+ transition-behavior: allow-discrete;
570
+
571
+ &:not([open])::backdrop {
572
+ background-color: transparent;
573
+ }
574
+ }
575
+
576
+ // From lg up: fill the fixed column and scroll the items inside it, without chaining to the
577
+ // page. (Bootstrap's layered `height: auto !important` can't be overridden, so cap the height.)
578
+ @media (width >= $lg) {
579
+ flex-direction: column;
580
+ max-height: 100%;
581
+ overflow: hidden;
582
+
583
+ .drawer-body {
584
+ flex: 1 1 auto;
585
+ flex-direction: column;
586
+ min-height: 0;
587
+ overflow-y: auto;
588
+ overflow-x: hidden;
589
+ overscroll-behavior: contain;
590
+ scrollbar-width: thin;
591
+ }
592
+ }
593
+ }
594
+
595
+ // Bootstrap 6 always reserves a scrollbar gutter on :root (unlayered), which leaves a strip wider than
596
+ // the 8px frame on the right even when the page doesn't scroll. In the layout, reserve none and use
597
+ // a thin scrollbar over the frame colour when the page does scroll.
598
+ :root:has(.ngb-layout) {
599
+ scrollbar-gutter: auto;
600
+ scrollbar-width: thin;
601
+ scrollbar-color: var(--fg-3) transparent;
602
+ }
@@ -0,0 +1,14 @@
1
+ // Structural styles for @angular/cdk/overlay (the overlay container, panes and backdrops).
2
+ // Bootstrap's z-index scale is used instead of the CDK's fixed 1000.
3
+ @use '@angular/cdk' as cdk;
4
+
5
+ @layer components {
6
+ @include cdk.overlay();
7
+
8
+ // The container holds popovers, tooltips and toasts; the top of that range keeps all of them
9
+ // above the sticky navbar and drawers. Modals use the native <dialog> top layer instead.
10
+ .cdk-overlay-container,
11
+ .cdk-global-overlay-wrapper {
12
+ z-index: var(--z-toast, 1070);
13
+ }
14
+ }
@@ -0,0 +1,29 @@
1
+ // Global tokens for @ngb-bootstrap/core additions.
2
+ // Built on Bootstrap 6's token system: override with
3
+ // @use "@ngb-bootstrap/core/styles" with ($ngb-root-tokens: (--ngb-focus-outline-offset: 3px));
4
+ @use 'bootstrap/scss/_config.scss' as bs;
5
+
6
+ $ngb-root-tokens: () !default;
7
+
8
+ // stylelint-disable-next-line scss/dollar-variable-default
9
+ $ngb-root-tokens: bs.defaults(
10
+ (
11
+ --ngb-transition-duration: 0.2s,
12
+ --ngb-focus-outline-offset: 2px,
13
+ // Layout (<ngb-layout>, <ngb-navbar>, <ngb-sidebar>, <ngb-footer>): Taiga UI docs proportions.
14
+ --ngb-layout-frame-bg: light-dark(#f6f6f6, #2f2f2f),
15
+ --ngb-layout-panel-bg: light-dark(#fff, #222),
16
+ --ngb-layout-frame-width: 0.5rem,
17
+ --ngb-layout-frame-radius: 1.5rem,
18
+ --ngb-layout-seam-width: 0.25rem,
19
+ --ngb-layout-seam-radius: 0.625rem,
20
+ --ngb-layout-divider-color: light-dark(rgb(0 0 0 / 10%), rgb(255 255 255 / 14%)),
21
+ --ngb-layout-content-padding: 1rem,
22
+ --ngb-navbar-height: 4.125rem,
23
+ --ngb-navbar-padding-x: 1rem,
24
+ --ngb-sidebar-width: 16.5rem,
25
+ --ngb-sidebar-collapsed-width: 4.375rem,
26
+ --ngb-sidebar-brand-bg: var(--ngb-layout-frame-bg),
27
+ ),
28
+ $ngb-root-tokens
29
+ );