@ecl/site-header 5.0.0-alpha.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.
@@ -0,0 +1,505 @@
1
+ /**
2
+ * Site Header EU
3
+ * @define site-header
4
+ */
5
+
6
+ @use 'sass:map';
7
+ @use '@ecl/grid/mixins/breakpoints';
8
+
9
+ // Exposed variables
10
+ $theme: null !default;
11
+ $site-header: null !default;
12
+ $language-list: null !default;
13
+
14
+ @use 'site-header-language-switcher' with (
15
+ $theme: $theme,
16
+ $language-switcher: map.get($site-header, 'language-switcher'),
17
+ $language-list: $language-list
18
+ );
19
+
20
+ .ecl-site-header {
21
+ background-color: map.get($site-header, 'background-color');
22
+ margin: 0;
23
+ position: relative;
24
+ z-index: map.get($theme, 'z-index', 'modal');
25
+
26
+ .ecl-site-header__inner {
27
+ box-shadow: var(--sh-4);
28
+ }
29
+
30
+ .ecl-site-header__background {
31
+ background: map.get($theme, 'color', 'white');
32
+ position: relative;
33
+ }
34
+
35
+ .ecl-menu,
36
+ .ecl-mega-menu {
37
+ background: transparent;
38
+ box-shadow: none;
39
+ display: flex;
40
+ min-height: map.get($site-header, 'logo-height-xs');
41
+ top: var(--s-m);
42
+ padding: 0;
43
+ position: absolute;
44
+ right: 0;
45
+ width: calc(44px + var(--s-m) * 2);
46
+
47
+ &.ecl-mega-menu--rtl,
48
+ &.ecl-menu--rtl {
49
+ left: 0;
50
+ right: auto;
51
+ }
52
+ }
53
+
54
+ .ecl-site-header__cta {
55
+ margin-bottom: var(--s-m);
56
+ position: relative;
57
+ width: max-content;
58
+ z-index: 1;
59
+ }
60
+
61
+ .ecl-site-header__cta:only-child {
62
+ margin-top: 0;
63
+ }
64
+
65
+ &.ecl-site-header--has-menu,
66
+ &.ecl-site-header--has-mega-menu {
67
+ .ecl-site-header__site-name + .ecl-site-header__cta {
68
+ margin-bottom: var(--s-m);
69
+ }
70
+ }
71
+
72
+ &.ecl-site-header-with-logo-s .ecl-menu__open,
73
+ &.ecl-site-header-with-logo-s .ecl-mega-menu__open {
74
+ top: 8px;
75
+
76
+ .ecl-link__icon:last-of-type {
77
+ top: 1px;
78
+ }
79
+ }
80
+
81
+ &.ecl-site-header-with-logo-m .ecl-menu__open,
82
+ &.ecl-site-header-with-logo-m .ecl-mega-menu__open {
83
+ top: 14px;
84
+ }
85
+
86
+ &.ecl-site-header-with-logo-l .ecl-menu__open,
87
+ &.ecl-site-header-with-logo-l .ecl-mega-menu__open {
88
+ top: 20px;
89
+ }
90
+
91
+ /* stylelint-disable no-descending-specificity */
92
+ .ecl-menu__open,
93
+ .ecl-mega-menu__open,
94
+ .ecl-menu[aria-expanded='true'] .ecl-menu__open,
95
+ .ecl-mega-menu[aria-expanded='true'] .ecl-mega-menu__open {
96
+ align-items: center;
97
+ border: 1px solid transparent;
98
+ box-sizing: border-box;
99
+ color: currentcolor;
100
+ height: 44px;
101
+ padding: calc(var(--s-xs) + 1px) 0;
102
+ position: relative;
103
+ z-index: 54;
104
+
105
+ &:hover {
106
+ border-color: var(--c-d);
107
+ border-width: 1px;
108
+ }
109
+ }
110
+
111
+ .ecl-menu__open .ecl-icon:last-of-type {
112
+ height: 1.5rem;
113
+ width: 1.5rem;
114
+ }
115
+
116
+ .ecl-mega-menu__open {
117
+ margin-inline-start: var(--s-m);
118
+ }
119
+
120
+ .ecl-menu[aria-expanded='true'] .ecl-menu__open,
121
+ .ecl-mega-menu[aria-expanded='true'] .ecl-mega-menu__open {
122
+ background-color: var(--c-p-20);
123
+ }
124
+ /* stylelint-enable no-descending-specificity */
125
+ }
126
+
127
+ .ecl-site-header__header {
128
+ position: relative;
129
+ z-index: 54;
130
+
131
+ .ecl-site-header--open-menu:not(.ecl-site-header--open-menu-start) & {
132
+ box-shadow: var(--sh-4);
133
+ }
134
+ }
135
+
136
+ .ecl-site-header__container {
137
+ display: flex;
138
+ flex-direction: column;
139
+ padding-bottom: var(--s-l);
140
+ padding-top: var(--s-l);
141
+ position: static;
142
+ }
143
+
144
+ .ecl-site-header__top {
145
+ align-items: center;
146
+ display: flex;
147
+ flex-grow: 1;
148
+ justify-content: space-between;
149
+ }
150
+
151
+ .ecl-site-header__logo-link {
152
+ flex-grow: 1;
153
+ }
154
+
155
+ .ecl-site-header__logo-image {
156
+ display: block;
157
+ height: map.get($site-header, 'logo-height-s');
158
+ max-width: 100%;
159
+
160
+ &.ecl-site-header__logo-image--m {
161
+ height: map.get($site-header, 'logo-height-m');
162
+ }
163
+
164
+ &.ecl-site-header__logo-image--l {
165
+ height: map.get($site-header, 'logo-height-l');
166
+ }
167
+ }
168
+
169
+ .ecl-site-header__action {
170
+ align-items: center;
171
+ display: flex;
172
+
173
+ .ecl-button:not(.ecl-search-form__button) {
174
+ margin-inline-start: var(--s-2xs);
175
+ }
176
+
177
+ .ecl-site-header--has-menu &,
178
+ .ecl-site-header--has-mega-menu & {
179
+ margin-inline-end: calc(44px + var(--s-2xs));
180
+ }
181
+
182
+ .ecl-form-group {
183
+ flex-grow: 0;
184
+ margin-inline-start: auto;
185
+ width: 100%;
186
+ }
187
+
188
+ .ecl-search-form__text-input {
189
+ box-sizing: border-box;
190
+ flex-grow: 0;
191
+ height: 44px;
192
+ width: 100%;
193
+ }
194
+ }
195
+
196
+ .ecl-site-header__login-box,
197
+ .ecl-site-header__search {
198
+ background-color: map.get($theme, 'color', 'white');
199
+ border: 1px solid var(--c-p-5);
200
+ box-shadow: var(--sh-3);
201
+ box-sizing: content-box;
202
+ color: var(--c-d);
203
+ display: none;
204
+ font: var(--f-ui-m);
205
+ left: 0;
206
+ margin-top: calc(var(--s-xs) - 1px);
207
+ padding: calc(var(--s-m) - 1px);
208
+ position: absolute;
209
+ width: calc(100% - var(--s-m) - var(--s-m));
210
+ z-index: map.get($theme, 'z-index', 'modal') + 1;
211
+ }
212
+
213
+ .ecl-site-header__login-box {
214
+ border-radius: map.get($theme, 'border-radius', 's');
215
+ box-sizing: border-box;
216
+ left: 0;
217
+ margin-top: var(--s-m);
218
+ width: 100%;
219
+
220
+ &::before {
221
+ @include site-header-language-switcher.arrow-up;
222
+
223
+ left: auto;
224
+ right: var(--ecl-login-arrow-position);
225
+ }
226
+
227
+ &.ecl-site-header__login-box--active {
228
+ display: block;
229
+ }
230
+ }
231
+
232
+ .ecl-site-header__language-selector,
233
+ .ecl-site-header__login-toggle,
234
+ .ecl-site-header__search-toggle {
235
+ align-items: center;
236
+ display: flex;
237
+ flex-direction: row;
238
+ font: var(--f-ui-m);
239
+ justify-content: center;
240
+
241
+ &:active,
242
+ &[aria-expanded='true'] {
243
+ background-color: var(--c-p-20);
244
+ }
245
+ }
246
+
247
+ .ecl-site-header__search--active {
248
+ display: flex;
249
+ margin-top: var(--s-m);
250
+
251
+ @include breakpoints.down('m') {
252
+ &::before {
253
+ @include site-header-language-switcher.arrow-up;
254
+
255
+ left: auto;
256
+ right: var(--ecl-search-arrow-position);
257
+ }
258
+ }
259
+ }
260
+
261
+ .ecl-site-header__language-container {
262
+ margin-top: var(--s-m);
263
+ }
264
+
265
+ .ecl-site-header__login-description {
266
+ margin: 0;
267
+ max-width: var(--max-w);
268
+ }
269
+
270
+ .ecl-site-header__login-separator {
271
+ background-color: var(--c-p-20);
272
+ border-width: 0;
273
+ height: 1px;
274
+ margin-bottom: var(--s-m);
275
+ margin-top: var(--s-m);
276
+ }
277
+
278
+ .ecl-site-header__language-icon {
279
+ align-items: center;
280
+ display: flex;
281
+ justify-content: center;
282
+ position: relative;
283
+ }
284
+
285
+ .ecl-site-header__banner-top {
286
+ border-top: 1px solid var(--c-p-20);
287
+ font: var(--f-m);
288
+ padding: var(--s-xs) 0;
289
+ }
290
+
291
+ .ecl-site-header__site-name {
292
+ border-top: 1px solid var(--c-p-20);
293
+ color: map.get($site-header, 'site-name-mobile-color');
294
+ font: var(--f-2xl);
295
+ padding: var(--s-l) 0;
296
+ }
297
+
298
+ .ecl-site-header__notification {
299
+ display: flex;
300
+
301
+ .ecl-notification {
302
+ margin: 0 0 var(--s-l);
303
+ }
304
+ }
305
+
306
+ // stylelint-disable plugin/selector-bem-pattern
307
+ .ecl-site-header .ecl-search-form__button .ecl-button__label {
308
+ display: none;
309
+ }
310
+
311
+ .ecl-site-header .ecl-search-form__button .ecl-button__icon {
312
+ display: block;
313
+ }
314
+ // stylelint-enable plugin/selector-bem-pattern
315
+
316
+ @include breakpoints.down('m') {
317
+ .ecl-site-header__login-toggle,
318
+ .ecl-site-header__search-toggle,
319
+ .ecl-site-header__language-selector {
320
+ font-size: 0;
321
+ line-height: 0;
322
+ padding: calc(var(--s-xs) - 1px) 0;
323
+
324
+ .ecl-icon {
325
+ height: 1.5rem;
326
+ width: 1.5rem;
327
+ }
328
+ }
329
+ }
330
+
331
+ /* stylelint-disable-next-line order/order */
332
+ @include breakpoints.up('s') {
333
+ .ecl-site-header__logo-link {
334
+ flex-grow: 0;
335
+ }
336
+ }
337
+
338
+ @include breakpoints.up('m') {
339
+ .ecl-site-header__logo-link {
340
+ margin-top: 0;
341
+ }
342
+ /* stylelint-disable-next-line plugin/selector-bem-pattern */
343
+ .ecl-site-header .ecl-search-form {
344
+ max-width: 100%;
345
+ }
346
+ }
347
+
348
+ @include breakpoints.up('l') {
349
+ .ecl-site-header {
350
+ .ecl-site-header__cta {
351
+ align-self: center;
352
+ margin: var(--s-xs) 0;
353
+
354
+ &:only-child {
355
+ margin-top: var(--s-xs);
356
+ }
357
+ }
358
+
359
+ &.ecl-site-header--has-menu {
360
+ box-shadow: none;
361
+ }
362
+
363
+ &.ecl-site-header--has-mega-menu .ecl-site-header__header {
364
+ box-shadow: none;
365
+ }
366
+
367
+ .ecl-menu {
368
+ background: map.get($site-header, 'gradient-background');
369
+ min-height: auto;
370
+ position: static;
371
+ width: 100%;
372
+ }
373
+
374
+ .ecl-mega-menu {
375
+ background: map.get($site-header, 'gradient-background');
376
+ position: relative;
377
+ top: 0;
378
+ width: 100%;
379
+ }
380
+
381
+ &.ecl-site-header--has-menu,
382
+ &.ecl-site-header--has-mega-menu {
383
+ .ecl-site-header__action {
384
+ margin-inline-end: 0;
385
+ }
386
+ }
387
+ }
388
+
389
+ .ecl-site-header__banner {
390
+ box-shadow: none;
391
+
392
+ .ecl-container {
393
+ display: flex;
394
+ position: relative;
395
+ }
396
+ }
397
+
398
+ .ecl-site-header__site-name {
399
+ align-self: center;
400
+ color: map.get($site-header, 'site-name-desktop-color');
401
+ flex-grow: 1;
402
+ font: var(--f-2xl);
403
+ margin-inline-end: 0;
404
+ }
405
+
406
+ .ecl-site-header__container {
407
+ align-items: flex-end;
408
+ flex-direction: row;
409
+ padding-bottom: var(--s-l);
410
+ padding-top: var(--s-l);
411
+ }
412
+
413
+ .ecl-site-header__top {
414
+ align-items: flex-end;
415
+ }
416
+
417
+ .ecl-site-header__logo-link {
418
+ margin-bottom: 0;
419
+ }
420
+
421
+ .ecl-site-header__logo-image {
422
+ display: block;
423
+
424
+ &.ecl-site-header__logo-image--l {
425
+ height: map.get($site-header, 'logo-height-lg-l');
426
+ }
427
+ }
428
+
429
+ .ecl-site-header__action {
430
+ .ecl-button--icon-only .ecl-button__icon {
431
+ height: map.get($theme, 'icon', 'xs');
432
+ width: map.get($theme, 'icon', 'xs');
433
+ }
434
+
435
+ .ecl-form-group {
436
+ width: map.get($site-header, 'search-width-l');
437
+ }
438
+ }
439
+
440
+ .ecl-site-header__login-container {
441
+ position: relative;
442
+ }
443
+
444
+ .ecl-site-header__notification .ecl-notification {
445
+ margin: 0 0 var(--s-l);
446
+ }
447
+
448
+ .ecl-site-header__login-box {
449
+ left: 50%;
450
+ min-width: 22rem;
451
+ padding: var(--s-l);
452
+ transform: translateX(-50%);
453
+ width: auto;
454
+
455
+ &::before {
456
+ left: 50%;
457
+ }
458
+ }
459
+
460
+ .ecl-site-header__login-toggle,
461
+ .ecl-site-header__language-selector {
462
+ .ecl-site-header__icon {
463
+ height: map.get($theme, 'icon', 'xs');
464
+ margin-inline-end: var(--s-xs);
465
+ width: map.get($theme, 'icon', 'xs');
466
+ }
467
+ }
468
+
469
+ .ecl-site-header__login-toggle {
470
+ margin-inline-end: var(--s-xs) !important;
471
+ }
472
+
473
+ .ecl-site-header__search-toggle {
474
+ display: none;
475
+ }
476
+
477
+ .ecl-site-header__search-container {
478
+ flex-grow: 1;
479
+ margin-inline-start: var(--s-l);
480
+
481
+ .ecl-site-header__search {
482
+ background-color: map.get($theme, 'color', 'white');
483
+ border-width: 0;
484
+ box-shadow: none;
485
+ display: flex;
486
+ margin: 0;
487
+ padding: 0;
488
+ position: relative;
489
+ top: 0;
490
+ width: auto;
491
+ }
492
+ }
493
+
494
+ // stylelint-disable plugin/selector-bem-pattern
495
+ .ecl-site-header .ecl-search-form__button .ecl-button__label {
496
+ display: block;
497
+ }
498
+ // stylelint-enable plugin/selector-bem-pattern
499
+ }
500
+
501
+ @include breakpoints.up('xl') {
502
+ .ecl-site-header__action .ecl-form-group {
503
+ width: map.get($site-header, 'search-width-xl');
504
+ }
505
+ }
@@ -0,0 +1,181 @@
1
+ {% apply spaceless %}
2
+
3
+ {#
4
+ Parameters:
5
+ - "icon_path" (string) (default: ''): URL to icons file
6
+ - "language_selector" (associative array) (default: predefined structure): Language switcher settings. format:
7
+ {
8
+ "href": (string) (default: ''): URL for switcher
9
+ "label": (string) (default: ''): Switcher language label, eg. 'English' in EU, 'EN' in ec.
10
+ "aria_label": (string) (default: ''): Switcher language aria label
11
+ "eu_category": (string) (default: ''): Label for EU languages
12
+ "non_eu_category": (string) (default: ''): Label for non-EU languages
13
+ "overlay" (associative array) (default: predefined structure): Overlay language switcher settings. format:
14
+ {
15
+ "close": (associative array) (default: {}): Close button, following ECL Button structure
16
+ "title": (string) (default: ''): Overlay title, eg. 'Select your language'.
17
+ "items": (array) (default: []): (array) (default: []): format: [
18
+ {
19
+ "lang" (string) (default: '') Item language code, eg. 'en', 'fr', etc.
20
+ "label" (string) (default: '') Item language label, eg. 'English', 'Français', etc.
21
+ "path" (string) (default: '') Item language URL eg. '/example#language_en'.
22
+ "active" (boolean) (default: false) define if item is the active language.
23
+ },
24
+ ],
25
+ "non_eu_items": (array) (default: []): (array) (default: []): format: [
26
+ {
27
+ "lang" (string) (default: '') Item language code, eg. 'en', 'fr', etc.
28
+ "label" (string) (default: '') Item language label, eg. 'English', 'Français', etc.
29
+ "path" (string) (default: '') Item language URL eg. '/example#language_en'.
30
+ "active" (boolean) (default: false) define if item is the active language.
31
+ },
32
+ ],
33
+ },
34
+ },
35
+ #}
36
+
37
+ {# Default variables #}
38
+
39
+ {% set _language_selector = language_selector|default({}) %}
40
+ {% set _icon_path = icon_path|default('') %}
41
+ {% set _label = _language_selector.label|default('') %}
42
+
43
+ {# Internal logic - Process properties #}
44
+
45
+ {% if _language_selector.overlay is defined and _language_selector.overlay is not empty %}
46
+ {% set _has_overlay = true %}
47
+ {% endif %}
48
+
49
+ {# Print the result #}
50
+
51
+ <div class="ecl-site-header__language">
52
+ <a
53
+ class="ecl-button ecl-button--tertiary ecl-site-header__language-selector"
54
+ href="{{ _language_selector.href|default('') }}"
55
+ data-ecl-language-selector
56
+ role="button"
57
+ aria-label="{{ _language_selector.aria_label|default('') ~ ' - ' ~ _label }}"
58
+ {% if _has_overlay is defined %}
59
+ aria-controls="language-list-overlay"
60
+ {% endif %}
61
+ >
62
+ <span class="ecl-site-header__language-icon">
63
+ {% include '@ecl/icon/icon.html.twig' with {
64
+ icon: {
65
+ path: _icon_path,
66
+ name: 'global',
67
+ size: 's'
68
+ },
69
+ as_image: true,
70
+ extra_classes: 'ecl-site-header__icon',
71
+ extra_accessibility: {
72
+ title: _label,
73
+ },
74
+ } only %}
75
+ </span>
76
+ {{- _label -}}
77
+ </a>
78
+
79
+ {% if _has_overlay is defined %}
80
+ <div class="ecl-site-header__language-container" id="language-list-overlay" hidden data-ecl-language-list-overlay aria-labelledby="ecl-site-header__language-title" role="dialog">
81
+ {# language list header #}
82
+ <div class="ecl-site-header__language-header">
83
+ <div
84
+ class="ecl-site-header__language-title"
85
+ id="ecl-site-header__language-title"
86
+ >
87
+ {{- _language_selector.overlay.title|default('') -}}
88
+ </div>
89
+ {% if _language_selector.overlay.close is not empty %}
90
+ {% include '@ecl/button/button.html.twig' with _language_selector.overlay.close|merge({
91
+ variant: 'tertiary',
92
+ extra_classes: 'ecl-site-header__language-close',
93
+ extra_attributes: [{
94
+ name: 'data-ecl-language-list-close',
95
+ }],
96
+ }) only %}
97
+ {% endif %}
98
+ </div>
99
+
100
+ <div
101
+ class="ecl-site-header__language-content"
102
+ data-ecl-language-list-content
103
+ >
104
+ {# EU languages #}
105
+ {% if _language_selector.overlay.items is not empty and _language_selector.overlay.items is iterable %}
106
+ <div class="ecl-site-header__language-category" data-ecl-language-list-eu>
107
+ {% if _language_selector.eu_category is not empty %}
108
+ <div class="ecl-site-header__language-category-title">
109
+ {{- _language_selector.eu_category -}}
110
+ </div>
111
+ {% endif %}
112
+ <ul class="ecl-site-header__language-list">
113
+ {% for _item in _language_selector.overlay.items %}
114
+ <li class="ecl-site-header__language-item">
115
+ {% set _link_label %}
116
+ <span class="ecl-site-header__language-link-code">{{ _item.lang|default('') }}</span>
117
+ <span class="ecl-site-header__language-link-label" lang="{{ _item.lang|default('') }}">{{ _item.label|default('') }}</span>
118
+ {% endset %}
119
+ {% set _link_classes = 'ecl-site-header__language-link' %}
120
+ {% if _item.active %}
121
+ {% set _link_classes = _link_classes ~ ' ecl-site-header__language-link--active' %}
122
+ {% endif %}
123
+ {% include '@ecl/link/link.html.twig' with {
124
+ link: _item|merge({
125
+ label: _link_label,
126
+ type: 'standalone',
127
+ no_visited: true
128
+ }),
129
+ extra_classes: _link_classes,
130
+ extra_attributes: [
131
+ { name: 'hreflang', value: _item.lang|default('')|e('html_attr') },
132
+ ],
133
+ } only %}
134
+ </li>
135
+ {% endfor %}
136
+ </ul>
137
+ </div>
138
+ {% endif %}
139
+
140
+ {# non-EU languages #}
141
+ {% if _language_selector.overlay.non_eu_items is not empty and _language_selector.overlay.non_eu_items is iterable %}
142
+ <div class="ecl-site-header__language-category" data-ecl-language-list-non-eu>
143
+ {% if _language_selector.non_eu_category is not empty %}
144
+ <div class="ecl-site-header__language-category-title">
145
+ {{- _language_selector.non_eu_category -}}
146
+ </div>
147
+ {% endif %}
148
+ <ul class="ecl-site-header__language-list">
149
+ {% for _item in _language_selector.overlay.non_eu_items %}
150
+ <li class="ecl-site-header__language-item">
151
+ {% set _link_label %}
152
+ <span class="ecl-site-header__language-link-code">{{ _item.lang|default('') }}</span>
153
+ <span class="ecl-site-header__language-link-label">{{ _item.label|default('') }}</span>
154
+ {% endset %}
155
+ {% set _link_classes = 'ecl-site-header__language-link' %}
156
+ {% if _item.active %}
157
+ {% set _link_classes = _link_classes ~ ' ecl-site-header__language-link--active' %}
158
+ {% endif %}
159
+ {% include '@ecl/link/link.html.twig' with {
160
+ link: _item|merge({
161
+ label: _link_label,
162
+ type: 'standalone',
163
+ no_visited: true
164
+ }),
165
+ extra_classes: _link_classes,
166
+ extra_attributes: [
167
+ { name: 'lang', value: _item.lang|default('') },
168
+ { name: 'hreflang', value: _item.lang|default('') },
169
+ ],
170
+ } only %}
171
+ </li>
172
+ {% endfor %}
173
+ </ul>
174
+ </div>
175
+ {% endif %}
176
+ </div>
177
+ </div>
178
+ {% endif %}
179
+ </div>
180
+
181
+ {% endapply %}