@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,48 @@
1
+ /**
2
+ * Site Header print
3
+ * @define site-header
4
+ */
5
+
6
+ @use 'sass:map';
7
+
8
+ // Exposed variables
9
+ $theme: null !default;
10
+
11
+ .ecl-site-header__logo-image {
12
+ height: 1.9cm;
13
+ margin-bottom: map.get($theme, 'spacing-print', 's');
14
+ margin-top: map.get($theme, 'spacing-print', 'm');
15
+ width: 7.2cm;
16
+ }
17
+
18
+ .ecl-site-header__action {
19
+ display: none;
20
+ }
21
+
22
+ .ecl-site-header__banner-top {
23
+ color: var(--c-d);
24
+ font: map.get($theme, 'font-prolonged-print', 'm');
25
+
26
+ .ecl-link {
27
+ color: var(--c-d);
28
+ }
29
+
30
+ .ecl-link::after {
31
+ display: none;
32
+ }
33
+ }
34
+
35
+ .ecl-site-header__banner {
36
+ font: map.get($theme, 'font-print', '3xl');
37
+ font-family: var(--ecl-font-family-print-alt);
38
+ font-weight: map.get($theme, 'font-weight-print', 'bold');
39
+ margin-top: map.get($theme, 'spacing-print', 'xs');
40
+ }
41
+
42
+ .ecl-site-header__logo-link::after {
43
+ display: none;
44
+ }
45
+
46
+ .ecl-site-header__logo-image-mobile {
47
+ display: none;
48
+ }
@@ -0,0 +1,434 @@
1
+ {% apply spaceless %}
2
+
3
+ {#
4
+ Parameters:
5
+ - "icon_path" (string) (default: ''): URL to icons file
6
+ - "banner_top" (object): Object of type link (link : { label, path })
7
+ - "logged" (boolean): Whether the user is logged in or not
8
+ - "menu" (associative array): Menu content, if any. Uses ECL Menu structure
9
+ - "mega_menu" (associative array): Menu content, if any. Uses ECL Mega Menu structure
10
+ - "site_name" (string) Site name
11
+ - "cta_link": (optional) (default: {}): Call to action link compatible with ECL Link component structure
12
+ - "logo" (associative array) (default: predefined structure): Logo image settings. format:
13
+ {
14
+ "title": (string) (default: ''): Logo title attribute.
15
+ "alt": (string) (default: ''): Logo alt attribute.
16
+ "href": (string) (default: ''): Logo URL.
17
+ "src_desktop": (string) (default: ''): Desktop logo image file path
18
+ "src_mobile": (string) (default: ''): Mobile logo image file path for EU only
19
+ "size": (string) (default: 'l'): Three sizes in desktop (s, m, l)
20
+ },
21
+ - "language_selector" (associative array) (default: predefined structure): Language switcher settings. format:
22
+ {
23
+ "href": (string) (default: ''): URL for switcher
24
+ "label": (string) (default: ''): Switcher language label, eg. 'English', 'Français', etc.
25
+ "aria_label": (string) (default: ''): Switcher language aria label
26
+ "code": (string) (default: ''): Switcher language code, eg. 'en', 'fr', etc.
27
+ "eu_category": (string) (default: ''): Label for EU languages
28
+ "non_eu_category": (string) (default: ''): Label for non-EU languages
29
+ "overlay" (associative array) (default: predefined structure): Overlay language switcher settings. format:
30
+ {
31
+ "close_label": (string) (default: ''): Close button label eg. 'Close'.
32
+ "title": (string) (default: ''): Overlay title, eg. 'Select your language'.
33
+ "items": (array) (default: []): (array) (default: []): format: [
34
+ {
35
+ "lang" (string) (default: '') Item language code, eg. 'en', 'fr', etc.
36
+ "label" (string) (default: '') Item language label, eg. 'English', 'Français', etc.
37
+ "path" (string) (default: '') Item language URL eg. '/example#language_en'.
38
+ "active" (boolean) (default: false) define if item is the active language.
39
+ },
40
+ ],
41
+ "non_eu_items": (array) (default: []): (array) (default: []): format: [
42
+ {
43
+ "lang" (string) (default: '') Item language code, eg. 'en', 'fr', etc.
44
+ "label" (string) (default: '') Item language label, eg. 'English', 'Français', etc.
45
+ "path" (string) (default: '') Item language URL eg. '/example#language_en'.
46
+ "active" (boolean) (default: false) define if item is the active language.
47
+ },
48
+ ],
49
+ },
50
+ },
51
+ - "search_toggle" (associate array) (default: {}) format:
52
+ {
53
+ "label": (string) Label of the element
54
+ "path": (string) Link of the element
55
+ }
56
+ - "login_box" (associate array) (default: {}) format:
57
+ {
58
+ "id": (string): Id of the box
59
+ "description": (string) default('Logged in as <last name>, <first name>')
60
+ "label": (string): Log out label
61
+ "href": (string): Url of the link
62
+ }
63
+ - "login_toggle" (associate array) (default: {}) format:
64
+ {
65
+ "label_not_logged": (string) Label for the anonymous users
66
+ "href_not_logged": (string) Link to the login form
67
+ "label_logged": (string) Label for the logged in users
68
+ "href_logged": (string) Link to the logout form
69
+ }
70
+ - "search_form" (associative array) (default: predefined structure): EC Search Form component structure
71
+ - "notification" (object) (default: {}): Optional notification compatible with ECL Notification component structure
72
+ - "extra_classes" (string) (default: '')
73
+ - "extra_attributes" (array) (default: data-ecl-auto-init="SiteHeaderStandardised"): format: [
74
+ {
75
+ "name" (string) (default: ''),
76
+ "value" (optional) (string)
77
+ ...
78
+ ],
79
+ #}
80
+
81
+ {# Default variables #}
82
+
83
+ {% set _logo = logo|default({}) %}
84
+ {% set _language_selector = language_selector|default({}) %}
85
+ {% set _logged = logged|default(false) %}
86
+ {% set _login_box = login_box|default({}) %}
87
+ {% set _login_toggle = login_toggle|default({}) %}
88
+ {% set _search_toggle = search_toggle|default({}) %}
89
+ {% set _icon_path = icon_path|default('') %}
90
+ {% set _menu = menu|default(false) %}
91
+ {% set _mega_menu = mega_menu|default(false) %}
92
+ {% set _site_name = site_name|default('') %}
93
+ {% set _cta_link = cta_link|default({}) %}
94
+ {% set _notification = notification|default({}) %}
95
+ {% set _extra_attributes = '' %}
96
+ {% set _css_class = 'ecl-site-header' %}
97
+ {% set _search_form_extra_attributes = [{ name: 'data-ecl-search-form' }] %}
98
+ {% set _search_input_extra_classes = 'ecl-search-form__text-input' %}
99
+ {% set _search_form_extra_classes = 'ecl-site-header__search' %}
100
+ {% set _search_input_extra_attributes = [] %}
101
+ {% set _search_button_extra_attributes = [] %}
102
+ {% set _search_button_label = '' %}
103
+
104
+ {# Merge options #}
105
+
106
+ {% set extra_attributes = [
107
+ { name: 'data-ecl-auto-init', value: 'SiteHeader' }
108
+ ]|merge(extra_attributes|default([]))
109
+ %}
110
+
111
+ {% if logo is defined and logo is not empty %}
112
+ {% set _logo = _logo|merge(logo) %}
113
+ {% endif %}
114
+
115
+ {% if login_toggle is defined and login_toggle is not empty %}
116
+ {% set _login_toggle = _login_toggle|merge(login_toggle) %}
117
+ {% endif %}
118
+
119
+ {% if login_box is defined and login_box is not empty %}
120
+ {% set _login_box = _login_box|merge(login_box) %}
121
+ {% endif %}
122
+
123
+ {% if language_selector is defined and language_selector is not empty %}
124
+ {% set _language_selector = _language_selector|merge(language_selector) %}
125
+ {% endif %}
126
+
127
+ {% if search_toggle is defined and search_toggle is not empty %}
128
+ {% set _search_toggle = _search_toggle|merge(search_toggle) %}
129
+ {% endif %}
130
+
131
+ {% if search_form is defined and search_form is not empty %}
132
+ {% if search_form.extra_attributes is defined and search_form.extra_attributes is not empty %}
133
+ {% set _search_form_extra_attributes = _search_form_extra_attributes|merge(search_form.extra_attributes) %}
134
+ {% endif %}
135
+ {% if search_form.extra_classes is defined and search_form.extra_classes is not empty %}
136
+ {% set _search_form_extra_classes = _search_form_extra_classes ~ ' ' ~ search_form.extra_classes %}
137
+ {% endif %}
138
+
139
+ {% if search_form.text_input is defined and search_form.text_input is not empty %}
140
+ {% if search_form.text_input.extra_classes is defined and search_form.text_input.extra_classes is not empty %}
141
+ {% set _search_input_extra_classes = _search_input_extra_classes ~ ' ' ~ _search_form.text_input.extra_classes %}
142
+ {% endif %}
143
+ {% if search_form.text_input.extra_attributes is defined and search_form.text_input.extra_attributes is not empty %}
144
+ {% set _search_input_extra_attributes = _search_input_extra_attributes|merge(search_form.text_input.extra_attributes) %}
145
+ {% endif %}
146
+ {% endif %}
147
+
148
+ {% if search_form.button is defined and search_form.button is not empty %}
149
+ {% if search_form.button.extra_classes is defined and search_form.button.extra_classes is not empty %}
150
+ {% set _search_button_extra_classes = _search_button_extra_classes ~ ' ' ~ search_form.button.extra_classes %}
151
+ {% endif %}
152
+ {% if search_form.button.extra_attributes is defined and search_form.button.extra_attributes is not empty %}
153
+ {% set _search_button_extra_attributes = _search_button_extra_attributes|merge(search_form.button.extra_attributes) %}
154
+ {% endif %}
155
+ {% if search_form.button.label is defined and search_form.button.label is not empty %}
156
+ {% set _search_button_label = search_form.button.label %}
157
+ {% endif %}
158
+ {% endif %}
159
+
160
+ {% set _search_form = {
161
+ label: search_form.label,
162
+ text_input: search_form.text_input|default({})|merge({
163
+ extra_input_classes: _search_input_extra_classes,
164
+ extra_attributes: _search_input_extra_attributes,
165
+ }),
166
+ button: search_form.button|default({})|merge({
167
+ label: _search_button_label,
168
+ icon: {
169
+ name: 'search',
170
+ path: _icon_path,
171
+ size: 'fluid',
172
+ },
173
+ icon_position: 'before',
174
+ extra_classes: _button_extra_classes,
175
+ extra_attributes: _search_button_extra_attributes,
176
+ }),
177
+ extra_attributes: _search_form_extra_attributes,
178
+ extra_classes: _search_form_extra_classes
179
+ }
180
+ %}
181
+ {% endif %}
182
+
183
+ {# Internal logic - Process properties #}
184
+
185
+ {% if _menu is not empty %}
186
+ {% set extra_classes = _css_class ~ '--has-menu ' ~ extra_classes %}
187
+ {% endif %}
188
+
189
+ {% if _mega_menu is not empty %}
190
+ {% set extra_classes = _css_class ~ '--has-mega-menu ' ~ extra_classes %}
191
+ {% endif %}
192
+
193
+ {% set _css_class = _css_class ~ ' ecl-site-header-with-logo-' ~ _logo.size|default('l') %}
194
+
195
+ {% if extra_classes is defined and extra_classes is not empty %}
196
+ {% set _css_class = _css_class ~ ' ' ~ extra_classes %}
197
+ {% endif %}
198
+
199
+ {% if extra_attributes is defined and extra_attributes is not empty and extra_attributes is iterable %}
200
+ {% for attr in extra_attributes %}
201
+ {% if attr.value is defined %}
202
+ {% set _extra_attributes = _extra_attributes ~ ' ' ~ attr.name|e('html_attr') ~ '="' ~ attr.value|e('html_attr') ~ '"' %}
203
+ {% else %}
204
+ {% set _extra_attributes = _extra_attributes ~ ' ' ~ attr.name|e('html_attr') %}
205
+ {% endif %}
206
+ {% endfor %}
207
+ {% endif %}
208
+
209
+ {# Print the result #}
210
+
211
+ <header
212
+ class="{{ _css_class }}"
213
+ {{ _extra_attributes|raw }}
214
+ >
215
+ <div class="ecl-site-header__inner">
216
+ <div class="ecl-site-header__background">
217
+ <div class="ecl-site-header__header">
218
+ <div class="ecl-site-header__container ecl-container">
219
+ <div class="ecl-site-header__top" data-ecl-site-header-top>
220
+ {# Logo #}
221
+ {% if _logo is not empty and _logo.src_desktop is not empty %}
222
+ {% set _label %}
223
+ {% set _picture = { sources: [{ src: _logo.src_desktop, media: 'l' }] } %}
224
+ {% if _logo.src_mobile is defined and _logo.src_mobile is not empty %}
225
+ {% set _picture = _picture|merge({
226
+ img: {
227
+ src: _logo.src_mobile,
228
+ alt: _logo.alt,
229
+ },
230
+ }) %}
231
+ {% else %}
232
+ {% set _picture = _picture|merge({
233
+ img: {
234
+ src: _logo.src_desktop,
235
+ alt: _logo.alt,
236
+ },
237
+ }) %}
238
+ {% endif %}
239
+ {% set image_classes = 'ecl-site-header__logo-image' %}
240
+ {% set image_classes = image_classes ~ ' ecl-site-header__logo-image--' ~ _logo.size|default('l') %}
241
+ {% include '@ecl/picture/picture.html.twig' with {
242
+ picture: _picture,
243
+ extra_classes: "ecl-site-header__picture",
244
+ extra_image_classes: image_classes,
245
+ extra_attributes: _logo.title is not empty ? [{ name: 'title', value: _logo.title }] : [],
246
+ } only %}
247
+ {% endset %}
248
+ {% include '@ecl/link/link.html.twig' with {
249
+ link: {
250
+ path: _logo.path,
251
+ label: _label,
252
+ type: 'standalone'
253
+ },
254
+ extra_classes: 'ecl-site-header__logo-link'
255
+ } only %}
256
+ {% endif %}
257
+
258
+ {# Header actions #}
259
+ <div class="ecl-site-header__action">
260
+
261
+ {# Login #}
262
+ {% if _login_toggle is not empty and _login_box is not empty %}
263
+ <div class="ecl-site-header__login-container">
264
+ {% if _logged %}
265
+ <a
266
+ class="ecl-button ecl-button--tertiary ecl-site-header__login-toggle"
267
+ href="{{ _login_toggle.href_logged }}"
268
+ aria-controls="{{ _login_box.id }}"
269
+ data-ecl-login-toggle
270
+ aria-expanded="false"
271
+ >
272
+ {% include '@ecl/icon/icon.html.twig' with {
273
+ icon: {
274
+ path: _icon_path,
275
+ name: 'logged-in',
276
+ size: 's'
277
+ },
278
+ as_image: true,
279
+ extra_classes: 'ecl-site-header__icon',
280
+ extra_accessibility: {
281
+ title: login_toggle.label_logged,
282
+ },
283
+ } only %}
284
+ {{- login_toggle.label_logged -}}
285
+ </a>
286
+ <div
287
+ id="{{ _login_box.id }}"
288
+ class="ecl-site-header__login-box"
289
+ data-ecl-login-box
290
+ >
291
+ <p class="ecl-site-header__login-description">
292
+ {{- _login_box.description -}}
293
+ </p>
294
+ <hr class="ecl-site-header__login-separator">
295
+ {% include '@ecl/link/link.html.twig' with {
296
+ link: {
297
+ label: _login_box.label,
298
+ path: _login_box.href,
299
+ type: 'standalone',
300
+ }
301
+ } only %}
302
+ </div>
303
+ {% else %}
304
+ <a
305
+ class="ecl-button ecl-button--tertiary ecl-site-header__login-toggle"
306
+ href="{{ _login_toggle.href_not_logged }}"
307
+ data-ecl-login-toggle
308
+ >
309
+ {% include '@ecl/icon/icon.html.twig' with {
310
+ icon: {
311
+ path: _icon_path,
312
+ name: 'log-in',
313
+ size: 's'
314
+ },
315
+ as_image: true,
316
+ extra_classes: 'ecl-site-header__icon',
317
+ extra_accessibility: {
318
+ title: login_toggle.label_not_logged,
319
+ },
320
+ } only %}
321
+ {{- login_toggle.label_not_logged -}}
322
+ </a>
323
+ {% endif %}
324
+ </div>
325
+ {% endif %}
326
+
327
+ {# Language selector #}
328
+ {% if _language_selector is not empty %}
329
+ {% include '@ecl/site-header/site-header-language-switcher.html.twig' with {
330
+ language_selector: _language_selector,
331
+ icon_path: _icon_path,
332
+ } only %}
333
+ {% endif %}
334
+
335
+ {# Search form #}
336
+ {% if _search_form is defined %}
337
+ <div class="ecl-site-header__search-container" role="search">
338
+ {% if _search_toggle is not empty %}
339
+ <a
340
+ class="ecl-button ecl-button--tertiary ecl-site-header__search-toggle"
341
+ href="{{ _search_toggle.href }}"
342
+ data-ecl-search-toggle="true"
343
+ aria-controls="search-form-id"
344
+ aria-expanded="false"
345
+ >
346
+ {%- include '@ecl/icon/icon.html.twig' with {
347
+ icon: {
348
+ name: 'search',
349
+ path: _icon_path,
350
+ size: 's',
351
+ },
352
+ as_image: true,
353
+ extra_classes: 'ecl-site-header__icon',
354
+ extra_accessibility: {
355
+ title: _search_toggle.label,
356
+ },
357
+ } only -%}
358
+ {{- _search_toggle.label -}}
359
+ </a>
360
+ {% endif %}
361
+ {% include '@ecl/search-form/search-form.html.twig' with _search_form only %}
362
+ </div>
363
+ {% endif %}
364
+ </div>
365
+ </div>
366
+ </div>
367
+ </div>
368
+ </div>
369
+
370
+ {# Notification #}
371
+ {% if _notification is defined and _notification is not empty %}
372
+ <div class="ecl-site-header__notification">
373
+ <div class="ecl-container">
374
+ {% include '@ecl/notification/notification.html.twig' with _notification|merge({
375
+ extra_attributes: _notification.extra_attributes|default([])|merge([{
376
+ name: 'data-ecl-site-header-notification',
377
+ }]),
378
+ }) only %}
379
+ </div>
380
+ </div>
381
+ {% endif %}
382
+
383
+ {# Banner top #}
384
+ {% if banner_top is defined and banner_top is not empty %}
385
+ <div class="ecl-site-header__banner-top">
386
+ <div class="ecl-container">
387
+ {%- if banner_top.link is defined and banner_top.link is not empty %}
388
+ {% include '@ecl/link/link.html.twig' with banner_top|merge({
389
+ link: banner_top.link|merge({ type: 'standalone', no_visited: true}),
390
+ icon_path: _icon_path
391
+ }) only %}
392
+ {% else %}
393
+ {{ banner_top }}
394
+ {% endif -%}
395
+ </div>
396
+ </div>
397
+ {% endif %}
398
+
399
+ {# Site name and call to action (banner) #}
400
+ {% if _site_name is not empty or _cta_link is not empty %}
401
+ <div class="ecl-site-header__banner">
402
+ <div class="ecl-container">
403
+ {% if _site_name is not empty %}
404
+ <div class="ecl-site-header__site-name">{{ _site_name }}</div>
405
+ {% endif %}
406
+ {% if _cta_link is not empty and _cta_link.link is not empty %}
407
+ {% include '@ecl/link/link.html.twig' with _cta_link|merge({
408
+ link: _cta_link.link|merge({
409
+ type: 'cta',
410
+ }),
411
+ extra_classes: 'ecl-site-header__cta',
412
+ }) only %}
413
+ {% endif %}
414
+ </div>
415
+ </div>
416
+ {% endif %}
417
+ </div>
418
+
419
+ {# Menu #}
420
+ {% if _menu is defined and _menu is not empty %}
421
+ {% include '@ecl/menu/menu.html.twig' with _menu|merge({
422
+ site_name: _site_name,
423
+ icon_path: _icon_path,
424
+ }) only %}
425
+ {% endif %}
426
+ {% if _mega_menu is defined and _mega_menu is not empty %}
427
+ {% include '@ecl/mega-menu/mega-menu.html.twig' with _mega_menu|merge({
428
+ site_name: _site_name,
429
+ icon_path: _icon_path,
430
+ }) only %}
431
+ {% endif %}
432
+ </header>
433
+
434
+ {% endapply %}