@openeuropa/bcl-theme-default 1.10.4 → 1.10.6
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.
- package/css/oe-bcl-ckeditor5.min.css +1 -1
- package/css/oe-bcl-ckeditor5.min.css.map +1 -1
- package/css/oe-bcl-default.css +581 -91
- package/css/oe-bcl-default.css.map +1 -1
- package/css/oe-bcl-default.min.css +1 -1
- package/css/oe-bcl-default.min.css.map +1 -1
- package/js/oe-bcl-default.bundle.js +187 -0
- package/js/oe-bcl-default.bundle.js.map +1 -1
- package/js/oe-bcl-default.bundle.min.js +1 -1
- package/js/oe-bcl-default.bundle.min.js.map +1 -1
- package/js/oe-bcl-default.esm.js +186 -1
- package/js/oe-bcl-default.esm.js.map +1 -1
- package/js/oe-bcl-default.esm.min.js +1 -1
- package/js/oe-bcl-default.esm.min.js.map +1 -1
- package/js/oe-bcl-default.umd.js +187 -0
- package/js/oe-bcl-default.umd.js.map +1 -1
- package/js/oe-bcl-default.umd.min.js +1 -1
- package/js/oe-bcl-default.umd.min.js.map +1 -1
- package/package.json +5 -5
- package/src/js/index.esm.js +4 -0
- package/src/js/index.umd.js +4 -0
- package/src/js/main-navigation/main-navigation.js +42 -0
- package/src/js/mega-menu/mega-menu.js +177 -0
- package/src/scss/_header.scss +212 -111
- package/src/scss/_mega-menu.scss +432 -0
- package/src/scss/base/_colors.scss +3 -0
- package/src/scss/oe-bcl-default.scss +1 -0
- package/templates/bcl-button/button.html.twig +3 -2
- package/templates/bcl-header/header.html.twig +37 -6
- package/templates/bcl-mega-menu/mega-menu-items.html.twig +35 -0
- package/templates/bcl-mega-menu/mega-menu-submenu.html.twig +65 -0
- package/templates/bcl-mega-menu/mega-menu.html.twig +115 -0
- package/templates/bcl-navigation/navigation.html.twig +3 -1
- package/templates/bcl-offcanvas/offcanvas.html.twig +9 -6
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
/* stylelint-disable no-descending-specificity, declaration-no-important */
|
|
2
|
+
|
|
3
|
+
/* -------------------------------------
|
|
4
|
+
Design tokens & helpers
|
|
5
|
+
-------------------------------------- */
|
|
6
|
+
$mm-panel-height: 288px !default;
|
|
7
|
+
$mm-z-content: 2 !default;
|
|
8
|
+
$mm-gutter-x: map-get($spacers, 3) !default;
|
|
9
|
+
$mm-gutter-y: map-get($spacers, "2-5") !default;
|
|
10
|
+
|
|
11
|
+
/* Helpers */
|
|
12
|
+
@mixin link-reset {
|
|
13
|
+
text-decoration: none;
|
|
14
|
+
&:hover {
|
|
15
|
+
text-decoration: underline;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@mixin mm-item-padding($py: $mm-gutter-y, $px: $mm-gutter-x) {
|
|
20
|
+
padding: $py $px;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* -------------------------------------
|
|
24
|
+
Component
|
|
25
|
+
-------------------------------------- */
|
|
26
|
+
|
|
27
|
+
.bcl-mega-menu {
|
|
28
|
+
--bcl-mega-menu-zindex: 40;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The mega menu position should not be relative to its nav item.
|
|
32
|
+
.nav-item:has(> .bcl-mega-menu) {
|
|
33
|
+
@include media-breakpoint-up(lg) {
|
|
34
|
+
position: static;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Low-specificity defaults for interactive elements inside the component.
|
|
39
|
+
// This does not apply to the trigger, which should get styles from the navbar.
|
|
40
|
+
.bcl-mega-menu__container {
|
|
41
|
+
:where(a) {
|
|
42
|
+
@include link-reset;
|
|
43
|
+
}
|
|
44
|
+
:where(a, button) {
|
|
45
|
+
&:focus-visible {
|
|
46
|
+
outline: 2px solid $primary;
|
|
47
|
+
// Prevent outline from being cut off in scroll container.
|
|
48
|
+
outline-offset: -2px;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Disable page-level scroll while open, in lg+ viewport.
|
|
54
|
+
@include media-breakpoint-up(lg) {
|
|
55
|
+
body:has(.bcl-mega-menu > [aria-expanded="true"]) {
|
|
56
|
+
overflow-y: hidden;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Show a half-transparent page overlay in lg+ viewport.
|
|
61
|
+
@include media-breakpoint-up(lg) {
|
|
62
|
+
.bcl-mega-menu:has(> [aria-expanded="true"]) {
|
|
63
|
+
&::after {
|
|
64
|
+
position: absolute;
|
|
65
|
+
inset-inline: 0;
|
|
66
|
+
background: #fff;
|
|
67
|
+
opacity: 0.5;
|
|
68
|
+
content: "";
|
|
69
|
+
z-index: calc(var(--bcl-mega-menu-zindex) - 10);
|
|
70
|
+
// The overlay can be as tall as we want, because the body scroll is disabled.
|
|
71
|
+
block-size: 300vw;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Use '[class]' to bump specificity.
|
|
77
|
+
// The element also has .dropdown-menu, causing competing styles.
|
|
78
|
+
.bcl-mega-menu__container[class] {
|
|
79
|
+
// Only show when expanded.
|
|
80
|
+
// Use ARIA state instead of .show sibling hacks.
|
|
81
|
+
// @todo Explain why.
|
|
82
|
+
display: none;
|
|
83
|
+
.bcl-mega-menu > [aria-expanded="true"] + & {
|
|
84
|
+
display: block;
|
|
85
|
+
@include media-breakpoint-up(lg) {
|
|
86
|
+
display: flex;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Override the z-index from bootstrap .dropdown-menu.
|
|
90
|
+
z-index: var(--bcl-mega-menu-zindex);
|
|
91
|
+
// Transition animation for open/close.
|
|
92
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
93
|
+
transition:
|
|
94
|
+
opacity 0.15s ease,
|
|
95
|
+
transform 0.15s ease;
|
|
96
|
+
.bcl-mega-menu > [aria-expanded="true"] + & {
|
|
97
|
+
opacity: 1;
|
|
98
|
+
transform: none;
|
|
99
|
+
}
|
|
100
|
+
.bcl-mega-menu > [aria-expanded="false"] + & {
|
|
101
|
+
opacity: 0;
|
|
102
|
+
transform: translateY(-4px);
|
|
103
|
+
pointer-events: none;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
position: absolute;
|
|
108
|
+
inset-block-start: 0;
|
|
109
|
+
inset-inline-start: 0;
|
|
110
|
+
inline-size: 100%;
|
|
111
|
+
margin-block-start: 0;
|
|
112
|
+
padding: 0;
|
|
113
|
+
border: 0;
|
|
114
|
+
border-radius: 0;
|
|
115
|
+
|
|
116
|
+
@include media-breakpoint-up(lg) {
|
|
117
|
+
inset-block-start: 100%;
|
|
118
|
+
padding-block: map-get($spacers, "2-5");
|
|
119
|
+
border-bottom: var(--bs-border-width) var(--bs-border-style)
|
|
120
|
+
var(--bs-border-color);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Show a shadowy bar to separate content from links columns.
|
|
125
|
+
.bcl-mega-menu__container .shadow-container {
|
|
126
|
+
// In medium viewport, the content appears above the links.
|
|
127
|
+
// The shadowy bar is horizontal.
|
|
128
|
+
@include media-breakpoint-up(lg) {
|
|
129
|
+
position: relative;
|
|
130
|
+
.shadow-bg {
|
|
131
|
+
position: absolute;
|
|
132
|
+
inset-inline-start: 50%;
|
|
133
|
+
inset-block-end: 0;
|
|
134
|
+
inline-size: 100vw;
|
|
135
|
+
block-size: 8px;
|
|
136
|
+
transform: translateX(-50%);
|
|
137
|
+
box-shadow: 0 4px 5px 0 rgba(224, 229, 245, 0.5);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// In larger viewport, the content appears left of the links.
|
|
141
|
+
// The shadowy bar is vertical.
|
|
142
|
+
@include media-breakpoint-up(xl) {
|
|
143
|
+
block-size: 100%;
|
|
144
|
+
position: absolute;
|
|
145
|
+
inset-inline-end: 0;
|
|
146
|
+
inset-block-start: 0;
|
|
147
|
+
.shadow-bg {
|
|
148
|
+
inset-inline-start: auto;
|
|
149
|
+
inset-inline-end: 0;
|
|
150
|
+
block-size: 100%;
|
|
151
|
+
inline-size: 10px;
|
|
152
|
+
transform: none;
|
|
153
|
+
box-shadow: 4px 3px 4px 0 rgba(224, 229, 245, 0.5);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// The back button.
|
|
159
|
+
.bcl-mega-menu__back-button-block {
|
|
160
|
+
position: relative;
|
|
161
|
+
padding: 20px map-get($spacers, 1) 0;
|
|
162
|
+
> .btn-link {
|
|
163
|
+
@include link-reset;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Left column with the description and "Discover more" link.
|
|
168
|
+
.bcl-mega-menu__info {
|
|
169
|
+
> .content-block {
|
|
170
|
+
padding: $mm-gutter-x;
|
|
171
|
+
background: $primary-bg-subtle;
|
|
172
|
+
@include media-breakpoint-up(lg) {
|
|
173
|
+
margin-inline-end: 0;
|
|
174
|
+
background: $white;
|
|
175
|
+
padding-inline-end: map-get($spacers, 4);
|
|
176
|
+
// Allow vertical scrollbar if content is too tall.
|
|
177
|
+
max-block-size: $mm-panel-height;
|
|
178
|
+
overflow-y: auto;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
> .content-link {
|
|
182
|
+
@include link-reset;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Item lists on any level.
|
|
188
|
+
ul.bcl-mega-menu__items {
|
|
189
|
+
list-style: none;
|
|
190
|
+
margin: 0;
|
|
191
|
+
padding-inline-start: 0;
|
|
192
|
+
// Add a scrollbar in desktop viewport.
|
|
193
|
+
@include media-breakpoint-up(lg) {
|
|
194
|
+
block-size: $mm-panel-height;
|
|
195
|
+
overflow-y: auto;
|
|
196
|
+
}
|
|
197
|
+
// Add space above in mobile viewport.
|
|
198
|
+
@include media-breakpoint-down(lg) {
|
|
199
|
+
margin: 1rem 0 0;
|
|
200
|
+
}
|
|
201
|
+
// Style the items.
|
|
202
|
+
> li {
|
|
203
|
+
// In mobile, items are separated by a border.
|
|
204
|
+
@include media-breakpoint-down(lg) {
|
|
205
|
+
&:not(:first-child) > * {
|
|
206
|
+
border-top: 1px solid $primary-bg-subtle;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
> span,
|
|
210
|
+
> a,
|
|
211
|
+
> button {
|
|
212
|
+
@include mm-item-padding();
|
|
213
|
+
// Use flex for icon spacing.
|
|
214
|
+
display: flex;
|
|
215
|
+
gap: 1rem;
|
|
216
|
+
justify-content: space-between;
|
|
217
|
+
> svg {
|
|
218
|
+
flex-shrink: 0;
|
|
219
|
+
align-self: center;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
> a {
|
|
223
|
+
color: $link-color;
|
|
224
|
+
text-decoration: none;
|
|
225
|
+
|
|
226
|
+
&:hover {
|
|
227
|
+
text-decoration: underline;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
> a,
|
|
231
|
+
> button {
|
|
232
|
+
&:hover {
|
|
233
|
+
background: $primary-bg-subtle;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
> span,
|
|
237
|
+
> button {
|
|
238
|
+
color: $dark;
|
|
239
|
+
}
|
|
240
|
+
// Buttons are used for parent items.
|
|
241
|
+
> button {
|
|
242
|
+
// Buttons don't occupy full width by default.
|
|
243
|
+
width: 100%;
|
|
244
|
+
// Unset common button styles.
|
|
245
|
+
border: none;
|
|
246
|
+
border-radius: 0;
|
|
247
|
+
text-align: inherit;
|
|
248
|
+
background: none;
|
|
249
|
+
white-space: normal;
|
|
250
|
+
|
|
251
|
+
// Show an icon.
|
|
252
|
+
&::after {
|
|
253
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/%3E%3C/svg%3E");
|
|
254
|
+
flex-shrink: 0;
|
|
255
|
+
align-self: center;
|
|
256
|
+
content: "";
|
|
257
|
+
height: 1em;
|
|
258
|
+
width: 1em;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
&[aria-expanded="true"] {
|
|
262
|
+
background: $primary-bg-subtle;
|
|
263
|
+
@include media-breakpoint-up(lg) {
|
|
264
|
+
// Simulate a border-left without having to adjust the padding.
|
|
265
|
+
position: relative;
|
|
266
|
+
&::before {
|
|
267
|
+
content: "";
|
|
268
|
+
position: absolute;
|
|
269
|
+
width: 4px;
|
|
270
|
+
top: 0;
|
|
271
|
+
bottom: 0;
|
|
272
|
+
left: 0;
|
|
273
|
+
background-color: $primary;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// The see-all link is at the bottom of the list.
|
|
280
|
+
&:has(> a.see-all-button) {
|
|
281
|
+
position: sticky;
|
|
282
|
+
inset-block-start: 100%;
|
|
283
|
+
}
|
|
284
|
+
> a.see-all-button {
|
|
285
|
+
border-top: none;
|
|
286
|
+
&:after {
|
|
287
|
+
background: $neutral-border-color;
|
|
288
|
+
content: "";
|
|
289
|
+
block-size: 1px;
|
|
290
|
+
inset-inline-start: 0;
|
|
291
|
+
position: absolute;
|
|
292
|
+
inset-block-start: 0;
|
|
293
|
+
// Replicate horizontal padding of parent element.
|
|
294
|
+
inset-inline: $mm-gutter-x;
|
|
295
|
+
}
|
|
296
|
+
> svg {
|
|
297
|
+
inline-size: 0.8rem;
|
|
298
|
+
}
|
|
299
|
+
> span {
|
|
300
|
+
text-overflow: ellipsis;
|
|
301
|
+
overflow: hidden;
|
|
302
|
+
display: block;
|
|
303
|
+
white-space: nowrap;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// First submenu.
|
|
310
|
+
.bcl-mega-menu__menu {
|
|
311
|
+
// On desktop, sub-submenus are positioned relative to this one.
|
|
312
|
+
@include media-breakpoint-up(lg) {
|
|
313
|
+
position: relative;
|
|
314
|
+
// Avoid a space between the parent menu and the submenu.
|
|
315
|
+
@include padding-right(0);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Nested submenu.
|
|
320
|
+
// This element has the 'hidden' attribute, unless it is expanded.
|
|
321
|
+
.bcl-mega-menu__submenu {
|
|
322
|
+
// Position relative to the parent.
|
|
323
|
+
position: absolute;
|
|
324
|
+
// In mobile it covers the parent.
|
|
325
|
+
@include media-breakpoint-down(lg) {
|
|
326
|
+
inset: 0 0 auto;
|
|
327
|
+
min-height: 100%;
|
|
328
|
+
}
|
|
329
|
+
// In desktop, it appears next to the parent.
|
|
330
|
+
@include media-breakpoint-up(lg) {
|
|
331
|
+
block-size: 100%;
|
|
332
|
+
inset: 0 0 0 100%;
|
|
333
|
+
inline-size: 100%;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// In mobile, there is a white background that covers the viewport width.
|
|
337
|
+
@include media-breakpoint-down(lg) {
|
|
338
|
+
&:before {
|
|
339
|
+
position: absolute;
|
|
340
|
+
content: "";
|
|
341
|
+
left: 50%;
|
|
342
|
+
margin-left: -50vw;
|
|
343
|
+
width: 100vw;
|
|
344
|
+
top: 0;
|
|
345
|
+
height: 100%;
|
|
346
|
+
background: white;
|
|
347
|
+
z-index: -1;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
background: white;
|
|
352
|
+
// In desktop, it gets a light background.
|
|
353
|
+
@include media-breakpoint-up(lg) {
|
|
354
|
+
background: $primary-bg-subtle;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Layout for children
|
|
358
|
+
display: flex;
|
|
359
|
+
flex-direction: column;
|
|
360
|
+
|
|
361
|
+
> .__header {
|
|
362
|
+
// The title only shows in mobile.
|
|
363
|
+
> .__label {
|
|
364
|
+
@include media-breakpoint-up(lg) {
|
|
365
|
+
display: none;
|
|
366
|
+
}
|
|
367
|
+
@include mm-item-padding(map-get($spacers, 3));
|
|
368
|
+
margin: 0;
|
|
369
|
+
color: $dark;
|
|
370
|
+
background: $primary-bg-subtle;
|
|
371
|
+
display: block;
|
|
372
|
+
font-size: 20px;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Second level items column.
|
|
378
|
+
.bcl-mega-menu__second-submenu {
|
|
379
|
+
> .tab-content > .tab-pane {
|
|
380
|
+
// In desktop, the entire second-level list has a light blue background.
|
|
381
|
+
@include media-breakpoint-up(lg) {
|
|
382
|
+
background: $primary-bg-subtle;
|
|
383
|
+
}
|
|
384
|
+
// Hide other parts of the mega menu in mobile, when a sub-submenu is open.
|
|
385
|
+
@include media-breakpoint-down(lg) {
|
|
386
|
+
.bcl-mega-menu__container:has(&.active) {
|
|
387
|
+
.bcl-mega-menu__info,
|
|
388
|
+
.bcl-mega-menu__first-submenu {
|
|
389
|
+
display: none;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
// The panel title only shows in mobile.
|
|
394
|
+
> .panel-title {
|
|
395
|
+
@include media-breakpoint-up(lg) {
|
|
396
|
+
display: none;
|
|
397
|
+
}
|
|
398
|
+
@include mm-item-padding(map-get($spacers, 3));
|
|
399
|
+
margin: 0;
|
|
400
|
+
color: $dark;
|
|
401
|
+
background: $primary-bg-subtle;
|
|
402
|
+
display: block;
|
|
403
|
+
font-size: 20px;
|
|
404
|
+
}
|
|
405
|
+
// Items get a bit more space to the sides in xl viewport.
|
|
406
|
+
@include media-breakpoint-up(xl) {
|
|
407
|
+
> ul > li > * {
|
|
408
|
+
margin: 0 map-get($spacers, "2-5");
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Set light-blue full-width background on some elements.
|
|
415
|
+
@include media-breakpoint-down(lg) {
|
|
416
|
+
.bcl-mega-menu__submenu > .__header,
|
|
417
|
+
.bcl-mega-menu .content-block,
|
|
418
|
+
.bcl-mega-menu__back-button-block {
|
|
419
|
+
position: relative;
|
|
420
|
+
&::before {
|
|
421
|
+
position: absolute;
|
|
422
|
+
inset-inline-start: 50%;
|
|
423
|
+
content: "";
|
|
424
|
+
background: $primary-bg-subtle;
|
|
425
|
+
inline-size: 100vw;
|
|
426
|
+
block-size: 100%;
|
|
427
|
+
inset-block-start: 0;
|
|
428
|
+
z-index: -1;
|
|
429
|
+
transform: translateX(-50%);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
@@ -78,6 +78,7 @@
|
|
|
78
78
|
@import "@openeuropa/bcl-theme-default/src/scss/badge";
|
|
79
79
|
@import "@openeuropa/bcl-theme-default/src/scss/multiselect";
|
|
80
80
|
@import "@openeuropa/bcl-theme-default/src/scss/multiselect-2";
|
|
81
|
+
@import "@openeuropa/bcl-theme-default/src/scss/mega-menu";
|
|
81
82
|
@import "@openeuropa/bcl-theme-default/src/scss/breadcrumb";
|
|
82
83
|
@import "@openeuropa/bcl-theme-default/src/scss/banners";
|
|
83
84
|
@import "@openeuropa/bcl-theme-default/src/scss/timeline";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{% apply spaceless %}
|
|
2
2
|
|
|
3
|
-
{#
|
|
3
|
+
{#
|
|
4
4
|
Parameters:
|
|
5
5
|
- label (string) (default: '')
|
|
6
6
|
- variant (string) (default: 'primary')
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
{% set _spinner = spinner|default({}) %}
|
|
39
39
|
{% set _show_spinner = show_spinner ?? false %}
|
|
40
40
|
{% set _clean_class = clean_class ?? false %}
|
|
41
|
+
{% set _remove_icon_spacers = remove_icon_spacers ?? false %}
|
|
41
42
|
|
|
42
43
|
{% set _classes = [] %}
|
|
43
44
|
{% if _clean_class == false %}
|
|
@@ -68,7 +69,7 @@
|
|
|
68
69
|
size: "fluid",
|
|
69
70
|
})
|
|
70
71
|
%}
|
|
71
|
-
{% if _label is not empty %}
|
|
72
|
+
{% if _label is not empty and not _remove_icon_spacers %}
|
|
72
73
|
{% if _icon.attributes is empty %}
|
|
73
74
|
{% set _icon = _icon|merge({
|
|
74
75
|
attributes: create_attribute()
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
{% set _project_logo = project_logo|default({}) %}
|
|
26
26
|
{% set _site_name = site_name|default('') %}
|
|
27
27
|
{% set _project_link = project_link|default('') %}
|
|
28
|
+
{% set _navbar_id = navbar_id|default('header-navbar-' ~ random(100)) %}
|
|
28
29
|
{% set _head = head|default({}) %}
|
|
29
30
|
{% set _breadcrumbs = breadcrumbs|default({}) %}
|
|
30
31
|
{% set _language_modal = language_modal|default({}) %}
|
|
@@ -51,10 +52,38 @@
|
|
|
51
52
|
<header
|
|
52
53
|
{{ attributes }}
|
|
53
54
|
>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
<nav
|
|
56
|
+
{{ _head.attributes.addClass(['navbar', 'navbar-expand-lg', 'navbar-light']) }}>
|
|
57
|
+
<div class='container'>
|
|
58
|
+
{% if _head.brand is not empty %}
|
|
59
|
+
<a class='navbar-brand' href='{{ _head.brand.link }}'>
|
|
60
|
+
{% for logo in _head.brand.logos %}
|
|
61
|
+
<img
|
|
62
|
+
src='{{ logo.src }}'
|
|
63
|
+
{% if logo.alt is not empty %}
|
|
64
|
+
alt='{{ logo.alt }}'
|
|
65
|
+
{% endif %}
|
|
66
|
+
{% if logo.class is not empty %}
|
|
67
|
+
class='{{ logo.class }}'
|
|
68
|
+
{% endif %}
|
|
69
|
+
/>
|
|
70
|
+
{% endfor %}
|
|
71
|
+
</a>
|
|
72
|
+
{% endif %}
|
|
73
|
+
<button
|
|
74
|
+
class="navbar-toggler bcl-navbar-toggler"
|
|
75
|
+
type="button"
|
|
76
|
+
data-bs-toggle="collapse"
|
|
77
|
+
data-bs-target='#{{ _navbar_id }}'
|
|
78
|
+
aria-controls='{{ _navbar_id }}'
|
|
79
|
+
aria-expanded="false"
|
|
80
|
+
aria-label="Toggle navigation"
|
|
81
|
+
>
|
|
82
|
+
<span class="navbar-toggler-icon"></span>
|
|
83
|
+
</button>
|
|
84
|
+
</div>
|
|
85
|
+
</nav>
|
|
86
|
+
|
|
58
87
|
|
|
59
88
|
<!-- project name -->
|
|
60
89
|
{% if _project_logo is not empty or _site_name is not empty %}
|
|
@@ -62,7 +91,6 @@
|
|
|
62
91
|
<div class="container">
|
|
63
92
|
{% if _project_link is not empty %}
|
|
64
93
|
<a
|
|
65
|
-
class="d-inline-block"
|
|
66
94
|
href="{{ _project_link }}"
|
|
67
95
|
>
|
|
68
96
|
{% endif %}
|
|
@@ -93,7 +121,10 @@
|
|
|
93
121
|
|
|
94
122
|
<!-- navbar -->
|
|
95
123
|
{% if _navbar is not empty %}
|
|
96
|
-
{% include '@oe-bcl/bcl-navbar/navbar.html.twig' with _navbar
|
|
124
|
+
{% include '@oe-bcl/bcl-navbar/navbar.html.twig' with _navbar|merge({
|
|
125
|
+
disable_collapse: true,
|
|
126
|
+
attributes: create_attribute().addClass('bcl-header__navbar collapse navbar-collapse').setAttribute('id', _navbar_id).setAttribute('aria-label', 'Main Navigation'),
|
|
127
|
+
}) only %}
|
|
97
128
|
{% endif %}
|
|
98
129
|
|
|
99
130
|
<!-- breadcrumbs -->
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{% apply spaceless %}
|
|
2
|
+
|
|
3
|
+
{% set _label = label ?? null %}
|
|
4
|
+
{% set _items = items ?? [] %}
|
|
5
|
+
{% set _icon_path = icon_path ?? '' %}
|
|
6
|
+
{% set _level = level ?? 1 %}
|
|
7
|
+
{% set _see_all = see_all ?? null %}
|
|
8
|
+
|
|
9
|
+
<ul class="bcl-mega-menu__items __level-{{ _level }}">
|
|
10
|
+
{% for _item in _items %}
|
|
11
|
+
{% set _li_attributes = _item.li_attributes ?? create_attribute() %}
|
|
12
|
+
{% if _item.items is defined and _item.items is not empty %}
|
|
13
|
+
{# This is a parent item. #}
|
|
14
|
+
<li{{ _li_attributes.addClass('__parent') }}>
|
|
15
|
+
{% include '@oe-bcl/bcl-mega-menu/mega-menu-submenu.html.twig' with _item|merge({
|
|
16
|
+
icon_path: _icon_path,
|
|
17
|
+
level: _level + 1,
|
|
18
|
+
}) only %}
|
|
19
|
+
</li>
|
|
20
|
+
{% else %}
|
|
21
|
+
{# This is a leaf item. #}
|
|
22
|
+
<li{{ _li_attributes.addClass('__leaf') }}>
|
|
23
|
+
{% if _item.path is empty %}
|
|
24
|
+
{# This is a nolink item. #}
|
|
25
|
+
<span{{ _item.attributes ?? '' }}>{{ _item.label }}</span>
|
|
26
|
+
{% else %}
|
|
27
|
+
{# This is a link. #}
|
|
28
|
+
{% include '@oe-bcl/bcl-link/link.html.twig' with _item only %}
|
|
29
|
+
{% endif %}
|
|
30
|
+
</li>
|
|
31
|
+
{% endif %}
|
|
32
|
+
{% endfor %}
|
|
33
|
+
</ul>
|
|
34
|
+
|
|
35
|
+
{% endapply %}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{% apply spaceless %}
|
|
2
|
+
|
|
3
|
+
{% set _items = items ?? [] %}
|
|
4
|
+
{% set _trigger = trigger ?? null %}
|
|
5
|
+
{% set _icon_path = icon_path ?? '' %}
|
|
6
|
+
{% set _level = level ?? 2 %}
|
|
7
|
+
{% set _see_all = see_all ?? null %}
|
|
8
|
+
|
|
9
|
+
{% set _trigger_id = _trigger.id|default('mm-trigger-' ~ random(10000)) %}
|
|
10
|
+
{% set _panel_id = 'mm-panel-' ~ _trigger_id %}
|
|
11
|
+
|
|
12
|
+
{% set _trigger_attributes = _trigger.attributes ?? create_attribute() %}
|
|
13
|
+
{% set _trigger = _trigger|merge({
|
|
14
|
+
attributes: _trigger_attributes
|
|
15
|
+
.setAttribute('id', _trigger_id)
|
|
16
|
+
.setAttribute('aria-controls', _panel_id)
|
|
17
|
+
.setAttribute('aria-expanded', 'false')
|
|
18
|
+
.setAttribute('aria-haspopup', 'menu'),
|
|
19
|
+
remove_icon_spacers: true,
|
|
20
|
+
clean_class: true,
|
|
21
|
+
}) %}
|
|
22
|
+
{% include '@oe-bcl/bcl-button/button.html.twig' with _trigger only %}
|
|
23
|
+
|
|
24
|
+
{# Add an optional "See all" link as last item. #}
|
|
25
|
+
{% if _see_all is not empty %}
|
|
26
|
+
{# Wrap the label for an ellipsis. #}
|
|
27
|
+
{% set _see_all_label %}
|
|
28
|
+
<span>{{- _see_all.label -}}</span>
|
|
29
|
+
{% endset %}
|
|
30
|
+
{% set _see_all_attr = (_see_all.attributes is defined ? _see_all.attributes : create_attribute()) %}
|
|
31
|
+
{% set _see_all = _see_all|merge({
|
|
32
|
+
label: _see_all_label,
|
|
33
|
+
icon: {
|
|
34
|
+
name: 'arrow-right',
|
|
35
|
+
path: _icon_path,
|
|
36
|
+
},
|
|
37
|
+
li_attributes: create_attribute()
|
|
38
|
+
.addClass('__see_all'),
|
|
39
|
+
attributes: _see_all_attr
|
|
40
|
+
.addClass(['see-all-button'])
|
|
41
|
+
.setAttribute('aria-label', 'See all items in ‘' ~ _trigger.label ~ '’')
|
|
42
|
+
}) %}
|
|
43
|
+
{% set _items = _items|merge([_see_all]) %}
|
|
44
|
+
{% endif %}
|
|
45
|
+
{% set submenu_attributes = create_attribute()
|
|
46
|
+
.setAttribute('id', _panel_id)
|
|
47
|
+
.setAttribute('hidden', '')
|
|
48
|
+
.setAttribute('role', 'group')
|
|
49
|
+
.setAttribute('aria-labelledby', _trigger_id)
|
|
50
|
+
.addClass('bcl-mega-menu__submenu', '__level-' ~ _level)
|
|
51
|
+
%}
|
|
52
|
+
<div{{ submenu_attributes }}>
|
|
53
|
+
{% if _trigger %}
|
|
54
|
+
<div class="__header">
|
|
55
|
+
<p class="__label">{{ _trigger.label }}</p>
|
|
56
|
+
</div>
|
|
57
|
+
{% endif %}
|
|
58
|
+
{% include '@oe-bcl/bcl-mega-menu/mega-menu-items.html.twig' with {
|
|
59
|
+
items: _items,
|
|
60
|
+
icon_path: _icon_path,
|
|
61
|
+
level: _level,
|
|
62
|
+
} only %}
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
{% endapply %}
|