@orangesk/orange-design-system 2.0.0-beta.30 → 2.0.0-beta.32
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/README.md +7 -7
- package/build/appstore.svg +31 -0
- package/build/components/Breadcrumbs/style.css +1 -1
- package/build/components/Breadcrumbs/style.css.map +1 -1
- package/build/components/Carousel/style.css +1 -1
- package/build/components/Carousel/style.css.map +1 -1
- package/build/components/Footer/style.css +1 -1
- package/build/components/Footer/style.css.map +1 -1
- package/build/components/Megamenu/style.css +1 -1
- package/build/components/Megamenu/style.css.map +1 -1
- package/build/components/Preview/style.css +1 -1
- package/build/components/Preview/style.css.map +1 -1
- package/build/components/PromoBanner/style.css +1 -1
- package/build/components/PromoBanner/style.css.map +1 -1
- package/build/components/index.js +1 -1
- package/build/components/index.js.map +1 -1
- package/build/components/tsconfig.tsbuildinfo +1 -1
- package/build/components/types/index.d.ts +17 -2
- package/build/components/types/src/components/Carousel/Carousel.static.d.ts +1 -11
- package/build/components/types/src/components/Footer/Footer.static.d.ts +21 -0
- package/build/components/types/src/components/Footer/constants.d.ts +12 -2
- package/build/components/types/src/components/Footer/data.d.ts +5 -0
- package/build/components/types/src/components/Footer/static.d.ts +21 -0
- package/build/components/types/src/components/Megamenu/Megamenu.d.ts +4 -2
- package/build/components/types/src/components/Megamenu/Megamenu.static.d.ts +16 -5
- package/build/components/types/src/components/Megamenu/MegamenuBlog.d.ts +1 -1
- package/build/components/types/src/components/Megamenu/MegamenuSearchContent.d.ts +10 -0
- package/build/components/types/src/components/Megamenu/MyOrangeMobilePanel.d.ts +6 -0
- package/build/components/types/src/components/Megamenu/constants.d.ts +15 -0
- package/build/components/types/src/components/Megamenu/data.d.ts +21 -0
- package/build/components/types/src/components/Megamenu/ids.d.ts +11 -0
- package/build/components/types/src/components/PromoBanner/PromoBanner.d.ts +5 -1
- package/build/components/types/src/components/index.d.ts +2 -1
- package/build/googleplay.svg +52 -0
- package/build/lib/base.css.map +1 -1
- package/build/lib/components.css +1 -1
- package/build/lib/components.css.map +1 -1
- package/build/lib/footer.css +1 -1
- package/build/lib/footer.css.map +1 -1
- package/build/lib/footer.js +2 -0
- package/build/lib/footer.js.map +1 -0
- package/build/lib/megamenu.css +1 -1
- package/build/lib/megamenu.css.map +1 -1
- package/build/lib/megamenu.js +1 -1
- package/build/lib/megamenu.js.map +1 -1
- package/build/lib/scripts.js +1 -1
- package/build/lib/scripts.js.map +1 -1
- package/build/lib/style.css +1 -1
- package/build/lib/style.css.map +1 -1
- package/build/lib/tsconfig.tsbuildinfo +1 -1
- package/build/lib/utilities.css +1 -1
- package/build/lib/utilities.css.map +1 -1
- package/build/search-index.json +8 -4
- package/package.json +12 -12
- package/src/components/Breadcrumbs/styles/mixins.scss +6 -1
- package/src/components/Carousel/Carousel.static.ts +60 -89
- package/src/components/Carousel/styles/mixins.scss +4 -12
- package/src/components/Footer/Footer.static.ts +130 -0
- package/src/components/Footer/Footer.tsx +142 -62
- package/src/components/Footer/constants.ts +12 -2
- package/src/components/Footer/data.ts +13 -0
- package/src/components/Footer/static.ts +59 -0
- package/src/components/Footer/styles/mixins.scss +122 -18
- package/src/components/Footer/styles/style.scss +63 -4
- package/src/components/Footer/tests/Footer.unit.test.js +2 -2
- package/src/components/Megamenu/Megamenu.static.ts +200 -90
- package/src/components/Megamenu/Megamenu.tsx +363 -615
- package/src/components/Megamenu/MegamenuBlog.tsx +192 -73
- package/src/components/Megamenu/MegamenuSearchContent.tsx +74 -0
- package/src/components/Megamenu/MyOrangeMobilePanel.tsx +127 -0
- package/src/components/Megamenu/constants.ts +15 -0
- package/src/components/Megamenu/data.ts +231 -0
- package/src/components/Megamenu/ids.ts +35 -0
- package/src/components/Megamenu/styles/mixins.scss +223 -16
- package/src/components/Megamenu/styles/style.scss +64 -0
- package/src/components/Preview/styles/style.scss +2 -1
- package/src/components/PromoBanner/PromoBanner.tsx +12 -1
- package/src/components/PromoBanner/styles/mixins.scss +31 -7
- package/src/components/PromoBanner/styles/style.scss +41 -0
- package/src/components/PromoBanner/tests/PromoBanner.unit.test.js +44 -0
- package/src/components/index.ts +3 -0
- package/src/styles/utilities/horizontal-scroll.scss +28 -11
|
@@ -185,55 +185,46 @@ export default class Carousel {
|
|
|
185
185
|
`.${CLASS_VIEWPORT_WRAPPER}`,
|
|
186
186
|
) as HTMLElement;
|
|
187
187
|
const scrollbar = this.instance?.scrollbar;
|
|
188
|
+
const swiper = this.instance;
|
|
188
189
|
|
|
189
|
-
if (!viewportWrapper || !scrollbar || !scrollbar.dragEl) {
|
|
190
|
+
if (!viewportWrapper || !scrollbar || !scrollbar.dragEl || !swiper) {
|
|
190
191
|
return;
|
|
191
192
|
}
|
|
192
193
|
|
|
193
|
-
const
|
|
194
|
-
const
|
|
194
|
+
const minTranslate = swiper.minTranslate();
|
|
195
|
+
const maxTranslate = swiper.maxTranslate();
|
|
196
|
+
const translateRange = Math.abs(maxTranslate - minTranslate);
|
|
195
197
|
|
|
196
|
-
|
|
197
|
-
if (slidesCount > slidesPerView) {
|
|
198
|
+
if (translateRange <= 1 || !swiper.enabled) {
|
|
198
199
|
if (scrollbar.el) {
|
|
199
|
-
scrollbar.el.style.display = "";
|
|
200
|
+
scrollbar.el.style.display = "none";
|
|
200
201
|
}
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
201
204
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// Example: 3 visible out of 5 total = 60% of scrollbar width
|
|
206
|
-
const visibleRatio = slidesPerView / slidesCount;
|
|
207
|
-
const dragSize = visibleRatio * scrollbarWidth;
|
|
208
|
-
// Ensure minimum 30px for usability
|
|
209
|
-
const finalDragSize = Math.max(dragSize, 30);
|
|
205
|
+
if (scrollbar.el) {
|
|
206
|
+
scrollbar.el.style.display = "";
|
|
207
|
+
}
|
|
210
208
|
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
const scrollbarWidth = scrollbar.el.offsetWidth;
|
|
210
|
+
const viewportWidth = viewportWrapper.clientWidth;
|
|
211
|
+
const offsetBefore = Number(swiper.params.slidesOffsetBefore) || 0;
|
|
212
|
+
const offsetAfter = Number(swiper.params.slidesOffsetAfter) || 0;
|
|
213
|
+
const contentWidth = this.track.scrollWidth + offsetBefore + offsetAfter;
|
|
213
214
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
const visibleRatio =
|
|
216
|
+
contentWidth > 0 ? Math.min(viewportWidth / contentWidth, 1) : 1;
|
|
217
|
+
const dragSize = visibleRatio * scrollbarWidth;
|
|
218
|
+
const finalDragSize = Math.max(dragSize, 30);
|
|
218
219
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const scrollRatio =
|
|
222
|
-
maxTranslateValue > 0
|
|
223
|
-
? Math.min(currentTranslate / maxTranslateValue, 1)
|
|
224
|
-
: 0;
|
|
220
|
+
scrollbar.dragEl.style.width = `${finalDragSize}px`;
|
|
221
|
+
scrollbar.dragEl.style.display = "";
|
|
225
222
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
223
|
+
const scrollRatio = Math.min(Math.max(swiper.progress || 0, 0), 1);
|
|
224
|
+
const maxDragTranslate = Math.max(scrollbarWidth - finalDragSize, 0);
|
|
225
|
+
const dragTranslateX = scrollRatio * maxDragTranslate;
|
|
229
226
|
|
|
230
|
-
|
|
231
|
-
} else {
|
|
232
|
-
// Hide scrollbar when all slides are visible (no scrolling needed)
|
|
233
|
-
if (scrollbar.el) {
|
|
234
|
-
scrollbar.el.style.display = "none";
|
|
235
|
-
}
|
|
236
|
-
}
|
|
227
|
+
scrollbar.dragEl.style.transform = `translate3d(${dragTranslateX}px, 0, 0)`;
|
|
237
228
|
};
|
|
238
229
|
|
|
239
230
|
// Initial update (double requestAnimationFrame ensures DOM is fully ready)
|
|
@@ -330,52 +321,44 @@ export default class Carousel {
|
|
|
330
321
|
}
|
|
331
322
|
}
|
|
332
323
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
* Also disabled when all slides fit on screen (slidesCount <= slidesPerView).
|
|
337
|
-
*/
|
|
338
|
-
private calculateBleedAmount(container: HTMLElement): number {
|
|
339
|
-
const containerWidth = container.offsetWidth;
|
|
340
|
-
const halfViewportWidth = window.innerWidth / 2;
|
|
341
|
-
const halfContainerWidth = containerWidth / 2;
|
|
342
|
-
let bleedAmount = halfViewportWidth - halfContainerWidth;
|
|
343
|
-
|
|
344
|
-
if (window.innerWidth >= 2560) {
|
|
345
|
-
bleedAmount = 0;
|
|
324
|
+
private applyBleedInsets(viewportWrapper: HTMLElement): void {
|
|
325
|
+
if (!this.instance || !this.instance.params) {
|
|
326
|
+
return;
|
|
346
327
|
}
|
|
347
328
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
bleedAmount = 0;
|
|
353
|
-
}
|
|
329
|
+
const viewportWidth =
|
|
330
|
+
document.documentElement.clientWidth ||
|
|
331
|
+
window.visualViewport?.width ||
|
|
332
|
+
window.innerWidth;
|
|
354
333
|
|
|
355
|
-
|
|
356
|
-
|
|
334
|
+
const rect = viewportWrapper.getBoundingClientRect();
|
|
335
|
+
const insetLeft = Math.max(Math.round(rect.left), 0);
|
|
336
|
+
const trailingSlidePadding = 20;
|
|
337
|
+
const insetAfter = Math.max(insetLeft - trailingSlidePadding, 0);
|
|
357
338
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
private applyBleedOffset(
|
|
363
|
-
viewportWrapper: HTMLElement,
|
|
364
|
-
bleedAmount: number,
|
|
365
|
-
): void {
|
|
366
|
-
// Safety check: ensure instance and params are initialized
|
|
367
|
-
if (!this.instance || !this.instance.params) {
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
339
|
+
const slidesPerView = Number(this.instance.params.slidesPerView) || 1;
|
|
340
|
+
const slidesCount = this.instance.slides.length;
|
|
341
|
+
const shouldDisableBleed =
|
|
342
|
+
viewportWidth >= 2560 || slidesCount <= slidesPerView;
|
|
370
343
|
|
|
371
|
-
|
|
372
|
-
const totalWidth = this.track.scrollWidth;
|
|
373
|
-
const contentFitsWithoutScroll = totalWidth <= visibleWidth + 5;
|
|
344
|
+
this.element.classList.toggle(CLASS_BLEED_RIGHT, !shouldDisableBleed);
|
|
374
345
|
|
|
375
|
-
if (
|
|
376
|
-
this.instance.params.
|
|
377
|
-
} else {
|
|
346
|
+
if (shouldDisableBleed) {
|
|
347
|
+
this.instance.params.slidesOffsetBefore = 0;
|
|
378
348
|
this.instance.params.slidesOffsetAfter = 0;
|
|
349
|
+
this.element.style.setProperty("--carousel-bleed-viewport-width", "100%");
|
|
350
|
+
this.element.style.setProperty("--carousel-bleed-margin-left", "0px");
|
|
351
|
+
} else {
|
|
352
|
+
this.instance.params.slidesOffsetBefore = insetLeft;
|
|
353
|
+
this.instance.params.slidesOffsetAfter = insetAfter;
|
|
354
|
+
this.element.style.setProperty(
|
|
355
|
+
"--carousel-bleed-viewport-width",
|
|
356
|
+
"100dvw",
|
|
357
|
+
);
|
|
358
|
+
this.element.style.setProperty(
|
|
359
|
+
"--carousel-bleed-margin-left",
|
|
360
|
+
"calc(50% - 50dvw)",
|
|
361
|
+
);
|
|
379
362
|
}
|
|
380
363
|
|
|
381
364
|
this.instance.update();
|
|
@@ -389,8 +372,7 @@ export default class Carousel {
|
|
|
389
372
|
*/
|
|
390
373
|
adjustConfigForBleedRight() {
|
|
391
374
|
requestAnimationFrame(() => {
|
|
392
|
-
|
|
393
|
-
if (!container || !this.instance) return;
|
|
375
|
+
if (!this.instance) return;
|
|
394
376
|
|
|
395
377
|
const viewportWrapper = this.element.querySelector(
|
|
396
378
|
`.${CLASS_VIEWPORT_WRAPPER}`,
|
|
@@ -398,18 +380,7 @@ export default class Carousel {
|
|
|
398
380
|
if (!viewportWrapper) return;
|
|
399
381
|
|
|
400
382
|
const updateBleedState = () => {
|
|
401
|
-
|
|
402
|
-
const slidesCount = this.instance?.slides.length || 0;
|
|
403
|
-
const shouldDisableBleed = slidesCount <= slidesPerView;
|
|
404
|
-
|
|
405
|
-
if (shouldDisableBleed) {
|
|
406
|
-
this.element.classList.remove(CLASS_BLEED_RIGHT);
|
|
407
|
-
} else {
|
|
408
|
-
this.element.classList.add(CLASS_BLEED_RIGHT);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
const bleedAmount = this.calculateBleedAmount(container);
|
|
412
|
-
this.applyBleedOffset(viewportWrapper, bleedAmount);
|
|
383
|
+
this.applyBleedInsets(viewportWrapper);
|
|
413
384
|
|
|
414
385
|
// Update margin compensation on resize
|
|
415
386
|
this.applyTrackMarginCompensation();
|
|
@@ -210,25 +210,17 @@
|
|
|
210
210
|
}
|
|
211
211
|
|
|
212
212
|
@mixin bleed-right-variant {
|
|
213
|
-
// Allow overflow on the left side at the carousel container level
|
|
214
213
|
overflow: visible;
|
|
215
214
|
|
|
216
215
|
.carousel__viewport-wrapper {
|
|
217
|
-
// Allow overflow from viewport
|
|
218
216
|
overflow: visible;
|
|
219
217
|
}
|
|
220
218
|
|
|
221
219
|
.carousel__viewport {
|
|
222
|
-
|
|
223
|
-
width:
|
|
220
|
+
width: var(--carousel-bleed-viewport-width, 100%);
|
|
221
|
+
max-width: var(--carousel-bleed-viewport-width, 100%);
|
|
224
222
|
margin-right: 0;
|
|
225
|
-
margin-left: 0 !important;
|
|
226
|
-
overflow:
|
|
227
|
-
overflow-y: hidden; // Still hide vertical overflow
|
|
228
|
-
|
|
229
|
-
// On very large screens (above 2K), stop the bleeding effect entirely
|
|
230
|
-
@media (min-width: 2560px) {
|
|
231
|
-
width: 100%;
|
|
232
|
-
}
|
|
223
|
+
margin-left: var(--carousel-bleed-margin-left, 0) !important;
|
|
224
|
+
overflow: hidden !important;
|
|
233
225
|
}
|
|
234
226
|
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { CLASS_ACCORDION_TOGGLE, CLASS_MENU_SECTION } from "./constants";
|
|
2
|
+
|
|
3
|
+
const MOBILE_MEDIA_QUERY = "(max-width: 479.98px)";
|
|
4
|
+
|
|
5
|
+
interface FooterSection {
|
|
6
|
+
element: HTMLElement;
|
|
7
|
+
toggle: HTMLButtonElement | null;
|
|
8
|
+
panel: HTMLElement | null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default class Footer {
|
|
12
|
+
element!: HTMLElement;
|
|
13
|
+
sections!: FooterSection[];
|
|
14
|
+
mediaQueryList!: MediaQueryList;
|
|
15
|
+
onToggleClick!: (event: Event) => void;
|
|
16
|
+
onMediaQueryChange!: () => void;
|
|
17
|
+
|
|
18
|
+
constructor(element: HTMLElement) {
|
|
19
|
+
if ((element as any).ODS_Footer) {
|
|
20
|
+
return (element as any).ODS_Footer;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.element = element;
|
|
24
|
+
this.sections = [];
|
|
25
|
+
this.mediaQueryList = window.matchMedia(MOBILE_MEDIA_QUERY);
|
|
26
|
+
|
|
27
|
+
this.onToggleClick = this.handleToggleClick.bind(this);
|
|
28
|
+
this.onMediaQueryChange = this.syncViewportState.bind(this);
|
|
29
|
+
|
|
30
|
+
(this.element as any).ODS_Footer = this;
|
|
31
|
+
|
|
32
|
+
this.init();
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static getInstance(el: HTMLElement): Footer | null {
|
|
37
|
+
return el && (el as any).ODS_Footer ? (el as any).ODS_Footer : null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
init(): void {
|
|
41
|
+
this.sections = Array.from(
|
|
42
|
+
this.element.querySelectorAll(
|
|
43
|
+
`[data-footer-section].${CLASS_MENU_SECTION}`,
|
|
44
|
+
),
|
|
45
|
+
).map((section) => {
|
|
46
|
+
const toggle = section.querySelector(
|
|
47
|
+
`.${CLASS_ACCORDION_TOGGLE}`,
|
|
48
|
+
) as HTMLButtonElement | null;
|
|
49
|
+
const panelId = toggle?.getAttribute("aria-controls");
|
|
50
|
+
const panel = panelId
|
|
51
|
+
? (this.element.querySelector(`#${panelId}`) as HTMLElement | null)
|
|
52
|
+
: null;
|
|
53
|
+
|
|
54
|
+
if (toggle) {
|
|
55
|
+
toggle.addEventListener("click", this.onToggleClick);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
element: section as HTMLElement,
|
|
60
|
+
toggle,
|
|
61
|
+
panel,
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
this.mediaQueryList.addEventListener("change", this.onMediaQueryChange);
|
|
66
|
+
|
|
67
|
+
this.syncViewportState();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private setSectionState(section: FooterSection, isExpanded: boolean): void {
|
|
71
|
+
if (!section.toggle || !section.panel) return;
|
|
72
|
+
|
|
73
|
+
section.toggle.setAttribute("aria-expanded", String(isExpanded));
|
|
74
|
+
section.panel.hidden = !isExpanded;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private syncViewportState(): void {
|
|
78
|
+
const isMobile = this.mediaQueryList.matches;
|
|
79
|
+
|
|
80
|
+
this.sections.forEach((section, index) => {
|
|
81
|
+
if (!section.toggle || !section.panel) return;
|
|
82
|
+
|
|
83
|
+
if (!isMobile) {
|
|
84
|
+
this.setSectionState(section, true);
|
|
85
|
+
section.element.removeAttribute("data-footer-mobile-initialized");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const isInitialized =
|
|
90
|
+
section.element.getAttribute("data-footer-mobile-initialized") ===
|
|
91
|
+
"true";
|
|
92
|
+
|
|
93
|
+
if (!isInitialized) {
|
|
94
|
+
this.setSectionState(section, index === 0);
|
|
95
|
+
section.element.setAttribute("data-footer-mobile-initialized", "true");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const isExpanded =
|
|
100
|
+
section.toggle.getAttribute("aria-expanded") === "true";
|
|
101
|
+
this.setSectionState(section, isExpanded);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private handleToggleClick(event: Event): void {
|
|
106
|
+
if (!this.mediaQueryList.matches) return;
|
|
107
|
+
|
|
108
|
+
const toggle = event.currentTarget as HTMLButtonElement;
|
|
109
|
+
const section = this.sections.find((item) => item.toggle === toggle);
|
|
110
|
+
|
|
111
|
+
if (!section || !section.toggle) return;
|
|
112
|
+
|
|
113
|
+
const isExpanded = section.toggle.getAttribute("aria-expanded") === "true";
|
|
114
|
+
this.setSectionState(section, !isExpanded);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
destroy(): void {
|
|
118
|
+
this.sections.forEach((section) => {
|
|
119
|
+
if (!section.toggle) return;
|
|
120
|
+
section.toggle.removeEventListener("click", this.onToggleClick);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
this.mediaQueryList.removeEventListener("change", this.onMediaQueryChange);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
update(): void {
|
|
127
|
+
this.destroy();
|
|
128
|
+
this.init();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import cx from "classnames";
|
|
3
3
|
|
|
4
|
-
import footerData, { socials } from "./data";
|
|
4
|
+
import footerData, { apps, socials } from "./data";
|
|
5
5
|
import {
|
|
6
|
+
CLASS_ACCORDION_ICON,
|
|
7
|
+
CLASS_ACCORDION_TOGGLE,
|
|
8
|
+
CLASS_BAR,
|
|
6
9
|
CLASS_BOTTOM,
|
|
7
10
|
CLASS_BOTTOM_COPYRIGHT,
|
|
8
11
|
CLASS_CONTAINER,
|
|
9
|
-
|
|
12
|
+
CLASS_DIVIDER,
|
|
13
|
+
CLASS_DIVIDER_HIDE_XS_DOWN,
|
|
10
14
|
CLASS_LIST,
|
|
15
|
+
CLASS_LIST_BREAK_SM_DOWN,
|
|
11
16
|
CLASS_LIST_INLINE,
|
|
17
|
+
CLASS_LIST_ITEM_LEAD,
|
|
18
|
+
CLASS_LIST_STACK_SM_DOWN,
|
|
19
|
+
CLASS_LIST_SPACE_SMALL,
|
|
12
20
|
CLASS_LOGO,
|
|
21
|
+
CLASS_MB_LARGE,
|
|
22
|
+
CLASS_MENU,
|
|
23
|
+
CLASS_MENU_SECTION,
|
|
13
24
|
CLASS_ROOT,
|
|
14
|
-
CLASS_SOCIALS,
|
|
15
25
|
CLASS_TITLE,
|
|
16
26
|
} from "./constants";
|
|
17
27
|
import { SocialButton } from "../SocialButton";
|
|
@@ -23,56 +33,113 @@ interface FooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
23
33
|
}
|
|
24
34
|
|
|
25
35
|
const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
|
|
36
|
+
const accordionIdPrefix = `footer-${React.useId().replace(/:/g, "")}`;
|
|
37
|
+
|
|
26
38
|
return (
|
|
27
|
-
<footer className={cx(CLASS_ROOT, className)}>
|
|
39
|
+
<footer className={cx(CLASS_ROOT, className)} data-footer>
|
|
28
40
|
<div className={CLASS_CONTAINER}>
|
|
29
|
-
<
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
<div className={cx(CLASS_BAR, CLASS_MB_LARGE)}>
|
|
42
|
+
<a
|
|
43
|
+
href="/"
|
|
44
|
+
aria-label="Odkaz na úvodnú stránku"
|
|
45
|
+
className={CLASS_LOGO}
|
|
46
|
+
>
|
|
47
|
+
<svg
|
|
48
|
+
width="48"
|
|
49
|
+
height="48"
|
|
50
|
+
viewBox="0 0 48 48"
|
|
51
|
+
fill="none"
|
|
52
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
53
|
+
>
|
|
54
|
+
<path d="M48 0H0V48H48V0Z" fill="black" />
|
|
55
|
+
<path
|
|
56
|
+
fillRule="evenodd"
|
|
57
|
+
clipRule="evenodd"
|
|
58
|
+
d="M48 48H0V0H48V48Z"
|
|
59
|
+
fill="#FF7900"
|
|
60
|
+
/>
|
|
61
|
+
<path
|
|
62
|
+
d="M5.9078 44.1298C4.1702 44.1298 2.60156 43.0229 2.60156 40.6047C2.60156 38.1855 4.16924 37.0796 5.9078 37.0796C7.6454 37.0796 9.21116 38.1865 9.21116 40.6047C9.21116 43.0229 7.64636 44.1298 5.9078 44.1298ZM5.9078 38.5657C4.59356 38.5657 4.35356 39.7494 4.35356 40.6047C4.35356 41.4591 4.59356 42.6457 5.9078 42.6457C7.22204 42.6457 7.46204 41.4601 7.46204 40.6047C7.46204 39.7503 7.22204 38.5657 5.9078 38.5657Z"
|
|
63
|
+
fill="white"
|
|
64
|
+
/>
|
|
65
|
+
<path
|
|
66
|
+
fillRule="evenodd"
|
|
67
|
+
clipRule="evenodd"
|
|
68
|
+
d="M10.418 37.2559H12.0912V38.0412C12.41 37.6179 13.1952 37.1196 13.9316 37.1196C14.0016 37.1196 14.088 37.1196 14.16 37.1283V38.7795H14.0736C13.3095 38.7795 12.4733 38.8985 12.2026 39.4927V43.9356H10.418V37.2559Z"
|
|
69
|
+
fill="white"
|
|
70
|
+
/>
|
|
71
|
+
<path
|
|
72
|
+
d="M18.831 43.3547C18.1777 43.7913 17.4087 44.0223 16.623 44.0181C15.375 44.0181 14.6367 43.1887 14.6367 42.0751C14.6367 40.5794 16.0114 39.7903 18.8444 39.4706V39.0981C18.8444 38.6133 18.4767 38.3291 17.7961 38.3291C17.1164 38.3291 16.5634 38.5989 16.165 39.0971L14.9794 38.4223C15.6015 37.5506 16.55 37.1147 17.8239 37.1147C19.5673 37.1147 20.5455 37.8703 20.5455 39.0981C20.5455 39.0981 20.5436 43.9269 20.5455 43.9394H18.9865L18.831 43.3547ZM16.3686 41.9474C16.3686 42.3967 16.6498 42.8162 17.1606 42.8162C17.7126 42.8162 18.2511 42.5877 18.7887 42.1125V40.5304C17.1471 40.733 16.3686 41.1573 16.3686 41.9474Z"
|
|
73
|
+
fill="white"
|
|
74
|
+
/>
|
|
75
|
+
<path
|
|
76
|
+
fillRule="evenodd"
|
|
77
|
+
clipRule="evenodd"
|
|
78
|
+
d="M21.9336 37.4342L23.3899 37.2336L23.5512 38.0256C24.371 37.4246 25.0229 37.1059 25.8437 37.1059C27.2184 37.1059 27.9288 37.8355 27.9288 39.2793V43.9296H26.1691V39.5846C26.1691 38.7667 25.9579 38.399 25.3214 38.399C24.7973 38.399 24.2731 38.6361 23.6741 39.1392V43.9296H21.9336V37.4342Z"
|
|
79
|
+
fill="white"
|
|
80
|
+
/>
|
|
81
|
+
<path
|
|
82
|
+
d="M32.2317 42.5003C33.5642 42.4907 33.6784 41.1323 33.6784 40.2491C33.6784 39.2008 33.1677 38.355 32.2192 38.355C31.5885 38.355 30.8819 38.8158 30.8819 40.3221C30.8819 41.1438 30.9405 42.5118 32.2317 42.5003ZM35.3671 37.2328V43.5582C35.3671 44.6718 35.2787 46.515 32.0983 46.5314C30.785 46.541 29.5658 46.013 29.3239 44.8677L31.0567 44.5874C31.1296 44.9166 31.3322 45.2421 32.3152 45.2421C33.2263 45.2421 33.664 44.8072 33.664 43.7637V42.9851L33.641 42.9611C33.3616 43.4622 32.9373 43.9355 31.9168 43.9355C30.3578 43.9355 29.1328 42.8546 29.1328 40.5966C29.1328 38.3627 30.3981 37.1118 31.817 37.109C33.1514 37.107 33.6429 37.7147 33.76 38.0334L33.736 38.0315L33.8829 37.2328H35.3671ZM39.5709 44.0584C37.6029 44.0584 36.4279 42.7912 36.4279 40.5928C36.4279 38.3704 37.6163 37.1051 39.5431 37.1051C41.4698 37.1051 42.616 38.3339 42.616 40.5045C42.616 40.6216 42.6016 40.7349 42.6016 40.8501H38.1539C38.1664 42.1173 38.6925 42.7557 39.7274 42.7557C40.3907 42.7557 40.8314 42.4869 41.2442 41.9003L42.5306 42.6136C41.9642 43.5611 40.9427 44.0584 39.5709 44.0584ZM40.8899 39.7096C40.8899 38.8178 40.3773 38.2917 39.5431 38.2917C38.7482 38.2917 38.2519 38.8062 38.1827 39.7106L40.8899 39.7096ZM45.6256 34.7214L44.9776 36.3966L44.3191 34.7214H43.7546V36.9294H44.1203V35.0872H44.1299L44.8547 36.9304H45.088L45.808 35.0872H45.8195V36.9304H46.1824V34.7224L45.6256 34.7214ZM41.56 34.7214V35.0152H42.2503V36.9304H42.6151V35.0152H43.3072V34.7214H41.56Z"
|
|
83
|
+
fill="white"
|
|
84
|
+
/>
|
|
85
|
+
</svg>
|
|
86
|
+
</a>
|
|
87
|
+
<ul
|
|
88
|
+
className={cx(
|
|
89
|
+
CLASS_LIST,
|
|
90
|
+
CLASS_LIST_INLINE,
|
|
91
|
+
CLASS_LIST_SPACE_SMALL,
|
|
92
|
+
)}
|
|
36
93
|
>
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
clipRule="evenodd"
|
|
51
|
-
d="M10.418 37.2559H12.0912V38.0412C12.41 37.6179 13.1952 37.1196 13.9316 37.1196C14.0016 37.1196 14.088 37.1196 14.16 37.1283V38.7795H14.0736C13.3095 38.7795 12.4733 38.8985 12.2026 39.4927V43.9356H10.418V37.2559Z"
|
|
52
|
-
fill="white"
|
|
53
|
-
/>
|
|
54
|
-
<path
|
|
55
|
-
d="M18.831 43.3547C18.1777 43.7913 17.4087 44.0223 16.623 44.0181C15.375 44.0181 14.6367 43.1887 14.6367 42.0751C14.6367 40.5794 16.0114 39.7903 18.8444 39.4706V39.0981C18.8444 38.6133 18.4767 38.3291 17.7961 38.3291C17.1164 38.3291 16.5634 38.5989 16.165 39.0971L14.9794 38.4223C15.6015 37.5506 16.55 37.1147 17.8239 37.1147C19.5673 37.1147 20.5455 37.8703 20.5455 39.0981C20.5455 39.0981 20.5436 43.9269 20.5455 43.9394H18.9865L18.831 43.3547ZM16.3686 41.9474C16.3686 42.3967 16.6498 42.8162 17.1606 42.8162C17.7126 42.8162 18.2511 42.5877 18.7887 42.1125V40.5304C17.1471 40.733 16.3686 41.1573 16.3686 41.9474Z"
|
|
56
|
-
fill="white"
|
|
57
|
-
/>
|
|
58
|
-
<path
|
|
59
|
-
fillRule="evenodd"
|
|
60
|
-
clipRule="evenodd"
|
|
61
|
-
d="M21.9336 37.4342L23.3899 37.2336L23.5512 38.0256C24.371 37.4246 25.0229 37.1059 25.8437 37.1059C27.2184 37.1059 27.9288 37.8355 27.9288 39.2793V43.9296H26.1691V39.5846C26.1691 38.7667 25.9579 38.399 25.3214 38.399C24.7973 38.399 24.2731 38.6361 23.6741 39.1392V43.9296H21.9336V37.4342Z"
|
|
62
|
-
fill="white"
|
|
63
|
-
/>
|
|
64
|
-
<path
|
|
65
|
-
d="M32.2317 42.5003C33.5642 42.4907 33.6784 41.1323 33.6784 40.2491C33.6784 39.2008 33.1677 38.355 32.2192 38.355C31.5885 38.355 30.8819 38.8158 30.8819 40.3221C30.8819 41.1438 30.9405 42.5118 32.2317 42.5003ZM35.3671 37.2328V43.5582C35.3671 44.6718 35.2787 46.515 32.0983 46.5314C30.785 46.541 29.5658 46.013 29.3239 44.8677L31.0567 44.5874C31.1296 44.9166 31.3322 45.2421 32.3152 45.2421C33.2263 45.2421 33.664 44.8072 33.664 43.7637V42.9851L33.641 42.9611C33.3616 43.4622 32.9373 43.9355 31.9168 43.9355C30.3578 43.9355 29.1328 42.8546 29.1328 40.5966C29.1328 38.3627 30.3981 37.1118 31.817 37.109C33.1514 37.107 33.6429 37.7147 33.76 38.0334L33.736 38.0315L33.8829 37.2328H35.3671ZM39.5709 44.0584C37.6029 44.0584 36.4279 42.7912 36.4279 40.5928C36.4279 38.3704 37.6163 37.1051 39.5431 37.1051C41.4698 37.1051 42.616 38.3339 42.616 40.5045C42.616 40.6216 42.6016 40.7349 42.6016 40.8501H38.1539C38.1664 42.1173 38.6925 42.7557 39.7274 42.7557C40.3907 42.7557 40.8314 42.4869 41.2442 41.9003L42.5306 42.6136C41.9642 43.5611 40.9427 44.0584 39.5709 44.0584ZM40.8899 39.7096C40.8899 38.8178 40.3773 38.2917 39.5431 38.2917C38.7482 38.2917 38.2519 38.8062 38.1827 39.7106L40.8899 39.7096ZM45.6256 34.7214L44.9776 36.3966L44.3191 34.7214H43.7546V36.9294H44.1203V35.0872H44.1299L44.8547 36.9304H45.088L45.808 35.0872H45.8195V36.9304H46.1824V34.7224L45.6256 34.7214ZM41.56 34.7214V35.0152H42.2503V36.9304H42.6151V35.0152H43.3072V34.7214H41.56Z"
|
|
66
|
-
fill="white"
|
|
67
|
-
/>
|
|
68
|
-
</svg>
|
|
69
|
-
</a>
|
|
94
|
+
<li className={CLASS_LIST_ITEM_LEAD}>Sledujte nás</li>
|
|
95
|
+
<li className={CLASS_LIST_BREAK_SM_DOWN} aria-hidden="true" />
|
|
96
|
+
{socials.map((social, index) => (
|
|
97
|
+
<li key={`footer-social-link-${index}`}>
|
|
98
|
+
<SocialButton
|
|
99
|
+
name={social.name}
|
|
100
|
+
href={social.url}
|
|
101
|
+
aria-label={social.label}
|
|
102
|
+
/>
|
|
103
|
+
</li>
|
|
104
|
+
))}
|
|
105
|
+
</ul>
|
|
106
|
+
</div>
|
|
70
107
|
|
|
71
|
-
<div className={
|
|
108
|
+
<div className={CLASS_MENU}>
|
|
72
109
|
{data.columns.map((column, index) => (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
110
|
+
// id pairs keep button/panel relationship unique when multiple footers exist on one page
|
|
111
|
+
<div
|
|
112
|
+
className={CLASS_MENU_SECTION}
|
|
113
|
+
data-footer-section
|
|
114
|
+
key={`footer-column-${index}`}
|
|
115
|
+
>
|
|
116
|
+
<button
|
|
117
|
+
type="button"
|
|
118
|
+
className={CLASS_ACCORDION_TOGGLE}
|
|
119
|
+
data-footer-toggle
|
|
120
|
+
id={`${accordionIdPrefix}-footer-section-toggle-${index}`}
|
|
121
|
+
aria-expanded={index === 0 ? "true" : "false"}
|
|
122
|
+
aria-controls={`${accordionIdPrefix}-footer-section-panel-${index}`}
|
|
123
|
+
>
|
|
124
|
+
<span className={CLASS_TITLE}>{column.title}</span>
|
|
125
|
+
<span className={CLASS_ACCORDION_ICON} aria-hidden="true">
|
|
126
|
+
<svg
|
|
127
|
+
width="24"
|
|
128
|
+
height="24"
|
|
129
|
+
viewBox="0 0 80 80"
|
|
130
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
131
|
+
>
|
|
132
|
+
<path
|
|
133
|
+
d="M66.666 33.333 40 60 13.333 33.333 20 26.667l20 20 20-20 6.666 6.666Z"
|
|
134
|
+
fill="currentColor"
|
|
135
|
+
/>
|
|
136
|
+
</svg>
|
|
137
|
+
</span>
|
|
138
|
+
</button>
|
|
139
|
+
<ul
|
|
140
|
+
className={CLASS_LIST}
|
|
141
|
+
id={`${accordionIdPrefix}-footer-section-panel-${index}`}
|
|
142
|
+
>
|
|
76
143
|
{column.links.map((link, linkIndex) => (
|
|
77
144
|
<li
|
|
78
145
|
className="mb-small"
|
|
@@ -86,18 +153,25 @@ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
|
|
|
86
153
|
))}
|
|
87
154
|
</div>
|
|
88
155
|
|
|
89
|
-
<hr />
|
|
156
|
+
<hr className={cx(CLASS_DIVIDER, CLASS_DIVIDER_HIDE_XS_DOWN)} />
|
|
90
157
|
|
|
91
|
-
<div className={
|
|
92
|
-
<ul
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
158
|
+
<div className={CLASS_BAR}>
|
|
159
|
+
<ul
|
|
160
|
+
className={cx(
|
|
161
|
+
CLASS_LIST,
|
|
162
|
+
CLASS_LIST_INLINE,
|
|
163
|
+
CLASS_LIST_SPACE_SMALL,
|
|
164
|
+
)}
|
|
165
|
+
>
|
|
166
|
+
<li className={CLASS_LIST_ITEM_LEAD}>
|
|
167
|
+
Stiahnite si aplikáciu Môj Orange
|
|
168
|
+
</li>
|
|
169
|
+
<li className={CLASS_LIST_BREAK_SM_DOWN} aria-hidden="true" />
|
|
170
|
+
{apps.map((app, index) => (
|
|
171
|
+
<li key={`footer-app-link-${index}`}>
|
|
172
|
+
<a href={app.url} target="_blank" rel="noopener noreferrer">
|
|
173
|
+
<img src={app.src} alt={app.label} />
|
|
174
|
+
</a>
|
|
101
175
|
</li>
|
|
102
176
|
))}
|
|
103
177
|
</ul>
|
|
@@ -110,12 +184,18 @@ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
|
|
|
110
184
|
</a>
|
|
111
185
|
</div>
|
|
112
186
|
|
|
113
|
-
<hr />
|
|
187
|
+
<hr className={CLASS_DIVIDER} />
|
|
114
188
|
|
|
115
189
|
<div className={CLASS_BOTTOM}>
|
|
116
|
-
<ul
|
|
190
|
+
<ul
|
|
191
|
+
className={cx(
|
|
192
|
+
CLASS_LIST,
|
|
193
|
+
CLASS_LIST_INLINE,
|
|
194
|
+
CLASS_LIST_STACK_SM_DOWN,
|
|
195
|
+
)}
|
|
196
|
+
>
|
|
117
197
|
{data.bottomLinks?.map((link, index) => (
|
|
118
|
-
<li
|
|
198
|
+
<li key={`footer-legal-link-${index}`}>
|
|
119
199
|
<a href={link.url}>{link.label}</a>
|
|
120
200
|
</li>
|
|
121
201
|
))}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
export const CLASS_ROOT = "footer";
|
|
2
2
|
|
|
3
3
|
export const CLASS_CONTAINER = `${CLASS_ROOT}__container`;
|
|
4
|
-
export const CLASS_GRID = `${CLASS_ROOT}__grid`;
|
|
5
4
|
export const CLASS_LOGO = `${CLASS_ROOT}__logo`;
|
|
6
5
|
export const CLASS_TITLE = `${CLASS_ROOT}__title`;
|
|
7
6
|
export const CLASS_LIST = `${CLASS_ROOT}__list`;
|
|
7
|
+
export const CLASS_LIST_SPACE_SMALL = `${CLASS_ROOT}__list--space-small`;
|
|
8
8
|
export const CLASS_LIST_INLINE = `${CLASS_ROOT}__list--inline`;
|
|
9
|
-
export const
|
|
9
|
+
export const CLASS_LIST_STACK_SM_DOWN = `${CLASS_ROOT}__list--stack-sm-down`;
|
|
10
|
+
export const CLASS_LIST_BREAK_SM_DOWN = `${CLASS_ROOT}__list-break--sm-down`;
|
|
11
|
+
export const CLASS_LIST_ITEM_LEAD = `${CLASS_ROOT}__list-item--lead`;
|
|
10
12
|
export const CLASS_BOTTOM = `${CLASS_ROOT}__bottom`;
|
|
11
13
|
export const CLASS_BOTTOM_COPYRIGHT = `${CLASS_ROOT}__bottom-copyright`;
|
|
14
|
+
export const CLASS_MENU = `${CLASS_ROOT}__menu`;
|
|
15
|
+
export const CLASS_MENU_SECTION = `${CLASS_ROOT}__menu-section`;
|
|
16
|
+
export const CLASS_BAR = `${CLASS_ROOT}__bar`;
|
|
17
|
+
export const CLASS_MB_LARGE = `${CLASS_ROOT}--mb-xlarge`;
|
|
18
|
+
export const CLASS_ACCORDION_TOGGLE = `${CLASS_ROOT}__accordion-toggle`;
|
|
19
|
+
export const CLASS_ACCORDION_ICON = `${CLASS_ROOT}__accordion-icon`;
|
|
20
|
+
export const CLASS_DIVIDER = `${CLASS_ROOT}__divider`;
|
|
21
|
+
export const CLASS_DIVIDER_HIDE_XS_DOWN = `${CLASS_DIVIDER}--hide-xs-down`;
|
|
@@ -95,4 +95,17 @@ export const socials: Array<{ name: SocialName; url: string; label: string }> =
|
|
|
95
95
|
},
|
|
96
96
|
];
|
|
97
97
|
|
|
98
|
+
export const apps = [
|
|
99
|
+
{
|
|
100
|
+
label: "App Store",
|
|
101
|
+
src: "/appstore.svg",
|
|
102
|
+
url: "https://apps.apple.com/sk/app/m%C3%B4j-orange/id519421813",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
label: "Google Play",
|
|
106
|
+
src: "/googleplay.svg",
|
|
107
|
+
url: "https://play.google.com/store/apps/details?id=sk.orange.android.orangego",
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
|
|
98
111
|
export default data;
|