@orangesk/orange-design-system 3.13.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/index.js +1 -1
- package/build/components/index.js.map +1 -1
- package/build/lib/base.css +1 -1
- package/build/lib/base.css.map +1 -1
- package/build/lib/breadcrumbs.css +2 -2
- package/build/lib/breadcrumbs.css.map +1 -1
- package/build/lib/components.css +1 -1
- package/build/lib/components.css.map +1 -1
- package/build/lib/fonts.css +1 -1
- package/build/lib/fonts.css.map +1 -1
- package/build/lib/footer.css +1 -1
- package/build/lib/footer.css.map +1 -1
- package/build/lib/footer.iife.js +2 -0
- package/build/lib/footer.iife.js.map +1 -0
- package/build/lib/megamenu.css +1 -1
- package/build/lib/megamenu.css.map +1 -1
- package/build/lib/megamenu.iife.js +2 -0
- package/build/lib/megamenu.iife.js.map +1 -0
- 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/package.json +10 -12
- package/src/components/AnchorNavigation/AnchorNavigation.static.ts +3 -4
- package/src/components/AnchorNavigation/tests/AnchorNavigation.megamenu.unit.test.ts +74 -0
- package/src/components/AnchorNavigation/tests/AnchorNavigation.unit.test.jsx +6 -0
- package/src/components/Breadcrumbs/styles/mixins.scss +6 -0
- package/src/components/Breadcrumbs/styles/rules.scss +30 -0
- package/src/components/Breadcrumbs/styles/style.scss +2 -26
- package/src/components/Carousel/styles/mixins.scss +0 -4
- package/src/components/Footer/classic.ts +3 -0
- package/src/components/Footer/styles/mixins.scss +32 -1
- package/src/components/Footer/styles/style.scss +8 -5
- package/src/components/Footer/tests/Footer.styles.unit.test.jsx +7 -2
- package/src/components/Megamenu/Megamenu.static.ts +25 -6
- package/src/components/Megamenu/classic.ts +3 -0
- package/src/components/Megamenu/styles/mixins.scss +114 -52
- package/src/components/Megamenu/styles/style.scss +6 -7
- package/src/components/Megamenu/tests/Megamenu.scroll.unit.test.ts +185 -0
- package/src/styles/base/globals.scss +1 -37
- package/src/styles/base/header-height-values.scss +9 -0
- package/src/styles/base/header-height.scss +50 -0
- package/src/styles/base/styleguide.scss +0 -1
- package/build/files/tone-of-voice.pdf +0 -26572
- package/build/images/card-device-example.png +0 -0
- package/build/images/cta-device.png +0 -0
- package/build/images/cta-plans.png +0 -0
- package/build/images/cta-renewal.png +0 -0
- package/build/images/device-mobile.png +0 -0
- package/build/images/form-validation-format.png +0 -0
- package/build/images/form-validation-info-structure.png +0 -0
- package/build/images/form-validation-semantics.png +0 -0
- package/build/images/forms-labels-grouping.png +0 -0
- package/build/images/forms-labels-instruction.png +0 -0
- package/build/images/forms-labels-structure.png +0 -0
- package/build/images/hero/example-lg.jpg +0 -0
- package/build/images/hero/example-lg@2x.jpg +0 -0
- package/build/images/hero/example-xl.jpg +0 -0
- package/build/images/hero/example-xl@2x.jpg +0 -0
- package/build/images/hero/example-xxl.jpg +0 -0
- package/build/images/hero/example-xxl@2x.jpg +0 -0
- package/build/images/hero/example.jpg +0 -0
- package/build/images/hero/example@2x.jpg +0 -0
- package/build/images/hero/old-vendor-2x.jpg +0 -0
- package/build/images/hero/old-vendor-lg-2x.jpg +0 -0
- package/build/images/hero/old-vendor-lg.jpg +0 -0
- package/build/images/hero/old-vendor-xl-2x.jpg +0 -0
- package/build/images/hero/old-vendor-xl.jpg +0 -0
- package/build/images/hero/old-vendor-xxl-2x.jpg +0 -0
- package/build/images/hero/old-vendor-xxl.jpg +0 -0
- package/build/images/hero/old-vendor.jpg +0 -0
- package/build/images/hero/photo-2x.jpg +0 -0
- package/build/images/hero/photo-lg-2x.jpg +0 -0
- package/build/images/hero/photo-lg.jpg +0 -0
- package/build/images/hero/photo-xl-2x.jpg +0 -0
- package/build/images/hero/photo-xl.jpg +0 -0
- package/build/images/hero/photo-xxl-2x.jpg +0 -0
- package/build/images/hero/photo-xxl.jpg +0 -0
- package/build/images/hero/photo.jpg +0 -0
- package/build/images/hero/single.png +0 -0
- package/build/images/hero/single@2x.png +0 -0
- package/build/images/hero/vendor-lg.png +0 -0
- package/build/images/hero/vendor-lg@2x.png +0 -0
- package/build/images/hero/vendor-xl.png +0 -0
- package/build/images/hero/vendor-xl@2x.png +0 -0
- package/build/images/hero/vendor-xxl.png +0 -0
- package/build/images/hero/vendor-xxl@2x.png +0 -0
- package/build/images/hero/vendor.png +0 -0
- package/build/images/hero/vendor@2x.png +0 -0
- package/build/images/phones.png +0 -0
- package/build/images/product-1.svg +0 -10
- package/build/images/product-2.svg +0 -14
- package/build/images/product-3.svg +0 -9
- package/build/images/tone-of-voice.jpg +0 -0
- package/build/lib/base.js +0 -3
- package/build/lib/breadcrumbs.js +0 -3
- package/build/lib/components.js +0 -3
- package/build/lib/fonts.js +0 -3
- package/build/lib/reset.js +0 -3
- package/build/lib/style.js +0 -3
- package/build/lib/utilities.js +0 -3
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orangesk/orange-design-system",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.x"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"build/",
|
|
10
|
+
"!build/images/**",
|
|
11
|
+
"!build/files/**",
|
|
10
12
|
"public/fonts/",
|
|
11
13
|
"public/footer-sprite-*.svg",
|
|
12
14
|
"src/components/",
|
|
@@ -35,7 +37,6 @@
|
|
|
35
37
|
"a11y-dialog": "^8.1.5",
|
|
36
38
|
"classnames": "^2.5.1",
|
|
37
39
|
"daypickr": "^0.3.4",
|
|
38
|
-
"diff2html": "^3.4.56",
|
|
39
40
|
"dompurify": "^3.4.17",
|
|
40
41
|
"html-react-parser": "6.1.9",
|
|
41
42
|
"lorem-ipsum": "3.0.0",
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"wnumb": "^1.2.0"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
|
-
"@babel/core": "8.0.
|
|
62
|
+
"@babel/core": "8.0.10",
|
|
62
63
|
"@babel/preset-env": "8.0.7",
|
|
63
64
|
"@babel/preset-react": "8.0.1",
|
|
64
65
|
"@babel/preset-typescript": "8.0.7",
|
|
@@ -71,32 +72,28 @@
|
|
|
71
72
|
"@rollup/plugin-terser": "1.0.2",
|
|
72
73
|
"@rollup/plugin-typescript": "^12.3.1",
|
|
73
74
|
"@rollup/plugin-url": "^8.0.2",
|
|
74
|
-
"@rollup/rollup-darwin-arm64": "^4.65.0",
|
|
75
75
|
"@testing-library/dom": "^10.4.2",
|
|
76
76
|
"@testing-library/jest-dom": "7.0.1",
|
|
77
77
|
"@testing-library/react": "^16.3.3",
|
|
78
78
|
"@testing-library/user-event": "^14.6.8",
|
|
79
|
-
"@types/node": "26.6.
|
|
79
|
+
"@types/node": "26.6.6",
|
|
80
80
|
"@types/react": "19.3.0",
|
|
81
81
|
"@types/react-dom": "19.3.0",
|
|
82
82
|
"@types/wnumb": "^1.2.3",
|
|
83
|
-
"@vitejs/plugin-react": "6.1.2",
|
|
84
83
|
"@vitest/coverage-v8": "5.0.5",
|
|
85
84
|
"@vitest/ui": "5.0.5",
|
|
86
85
|
"canvas": "^3.2.3",
|
|
87
|
-
"
|
|
88
|
-
"glob": "13.0.6",
|
|
86
|
+
"glob": "14.0.3",
|
|
89
87
|
"html-validate": "11.17.0",
|
|
90
88
|
"husky": "^9.1.7",
|
|
91
|
-
"identity-obj-proxy": "^3.0.0",
|
|
92
89
|
"jsdom": "30.1.3",
|
|
93
90
|
"lint-staged": "17.6.0",
|
|
94
91
|
"prettier": "^3.9.10",
|
|
95
|
-
"rollup": "^4.
|
|
92
|
+
"rollup": "^4.66.0",
|
|
96
93
|
"rollup-plugin-copy": "^3.5.0",
|
|
97
94
|
"rollup-plugin-dts": "^6.5.1",
|
|
98
95
|
"rollup-plugin-postcss": "^4.0.2",
|
|
99
|
-
"sass": "^1.
|
|
96
|
+
"sass": "^1.107.0",
|
|
100
97
|
"svg-sprite": "^2.0.4",
|
|
101
98
|
"typescript": "6.0.3",
|
|
102
99
|
"vitest": "5.0.5",
|
|
@@ -109,11 +106,12 @@
|
|
|
109
106
|
"scripts": {
|
|
110
107
|
"dev": "npm run sprite && npm run build:search-index && npm run build:preview-iframe && next dev",
|
|
111
108
|
"build": "npm run sprite && npm run build:search-index && npm run build:preview-iframe && next build",
|
|
112
|
-
"build:bundle": "pnpm run sprite && pnpm exec rollup -c && pnpm exec rollup -c rollup.megamenu.config.mjs && pnpm exec rollup -c rollup.footer.config.mjs && pnpm run verify:production-bundle",
|
|
109
|
+
"build:bundle": "pnpm run sprite && pnpm exec rollup -c && pnpm exec rollup -c rollup.megamenu.config.mjs && pnpm exec rollup -c rollup.footer.config.mjs && pnpm run verify:production-bundle && pnpm run verify:standalone-bundles",
|
|
113
110
|
"build:preview-iframe": "node scripts/build-preview-iframe-bundle.mjs",
|
|
114
111
|
"build:megamenu": "pnpm run sprite && pnpm exec rollup -c rollup.megamenu.config.mjs",
|
|
115
112
|
"build:footer": "pnpm run build:scss-exports && node scripts/build-footer-sprites.mjs && pnpm exec rollup -c rollup.footer.config.mjs",
|
|
116
113
|
"verify:production-bundle": "node scripts/verify-production-bundle.mjs",
|
|
114
|
+
"verify:standalone-bundles": "node scripts/verify-standalone-bundles.mjs",
|
|
117
115
|
"dev:footer": "npm run build:scss-exports && node scripts/build-footer-sprites.mjs && pnpm exec rollup -c rollup.footer.config.mjs --watch",
|
|
118
116
|
"build:scss-exports": "node scripts/build-scss-exports.js",
|
|
119
117
|
"build:search-index": "node scripts/mdx-search-index.js",
|
|
@@ -99,7 +99,8 @@ export default class AnchorNavigation {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
private getMegamenuOffsetHeight(): number {
|
|
102
|
-
|
|
102
|
+
// offsetHeight rounds fractional CSS pixels and can leave a visible seam.
|
|
103
|
+
return this.megamenuElement?.getBoundingClientRect().height || 0;
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
private updateStickyPosition(): void {
|
|
@@ -304,9 +305,7 @@ export default class AnchorNavigation {
|
|
|
304
305
|
}
|
|
305
306
|
|
|
306
307
|
private getTotalStickyOffset(): number {
|
|
307
|
-
const scrollOffset = this.
|
|
308
|
-
? this.megamenuElement.offsetHeight
|
|
309
|
-
: 0;
|
|
308
|
+
const scrollOffset = this.getMegamenuOffsetHeight();
|
|
310
309
|
const anchorNavOffset = this.element.offsetHeight;
|
|
311
310
|
return scrollOffset + anchorNavOffset;
|
|
312
311
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
import AnchorNavigation from "../AnchorNavigation.static";
|
|
4
|
+
|
|
5
|
+
describe("AnchorNavigation fractional Megamenu height", () => {
|
|
6
|
+
let instance: AnchorNavigation;
|
|
7
|
+
let menu: HTMLElement;
|
|
8
|
+
let anchor: HTMLElement;
|
|
9
|
+
let height: number;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
height = 80.5;
|
|
13
|
+
menu = document.createElement("nav");
|
|
14
|
+
menu.setAttribute("data-megamenu", "");
|
|
15
|
+
// jsdom has no layout; represent the browser's fractional and rounded APIs.
|
|
16
|
+
vi.spyOn(menu, "getBoundingClientRect").mockImplementation(
|
|
17
|
+
() => ({ height }) as DOMRect,
|
|
18
|
+
);
|
|
19
|
+
Object.defineProperty(menu, "offsetHeight", {
|
|
20
|
+
get: () => Math.round(height),
|
|
21
|
+
});
|
|
22
|
+
anchor = document.createElement("nav");
|
|
23
|
+
anchor.innerHTML = '<ul class="anchor-navigation__content-left"></ul>';
|
|
24
|
+
document.body.append(menu, anchor);
|
|
25
|
+
instance = new AnchorNavigation(anchor);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
instance.destroy();
|
|
30
|
+
menu.remove();
|
|
31
|
+
anchor.remove();
|
|
32
|
+
vi.restoreAllMocks();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("places the navigation at the fractional menu edge on initialization", () => {
|
|
36
|
+
expect(anchor.style.top).toBe("80.5px");
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("follows fractional animation heights through its ResizeObserver", () => {
|
|
40
|
+
height = 113.625;
|
|
41
|
+
const observer = (instance as any).resizeObserver;
|
|
42
|
+
observer.callback([], observer);
|
|
43
|
+
expect(anchor.style.top).toBe("113.625px");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("keeps the fractional menu offset when scrolling to a section", () => {
|
|
47
|
+
const section = document.createElement("section");
|
|
48
|
+
section.id = "fractional-section";
|
|
49
|
+
vi.spyOn(section, "getBoundingClientRect").mockReturnValue({
|
|
50
|
+
top: 600,
|
|
51
|
+
} as DOMRect);
|
|
52
|
+
document.body.append(section);
|
|
53
|
+
Object.defineProperty(anchor, "offsetHeight", { value: 50 });
|
|
54
|
+
const previousScrollY = window.scrollY;
|
|
55
|
+
Object.defineProperty(window, "scrollY", { configurable: true, value: 0 });
|
|
56
|
+
const scroll = vi.spyOn(window, "scrollTo").mockImplementation(() => {});
|
|
57
|
+
const link = document.createElement("a");
|
|
58
|
+
link.className = "anchor-navigation__item";
|
|
59
|
+
link.href = "#fractional-section";
|
|
60
|
+
anchor.append(link);
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
link.click();
|
|
64
|
+
expect(scroll).toHaveBeenCalledWith({ top: 469.5, behavior: "smooth" });
|
|
65
|
+
} finally {
|
|
66
|
+
Object.defineProperty(window, "scrollY", {
|
|
67
|
+
configurable: true,
|
|
68
|
+
value: previousScrollY,
|
|
69
|
+
writable: true,
|
|
70
|
+
});
|
|
71
|
+
section.remove();
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -628,6 +628,9 @@ describe("rendering AnchorNavigation", () => {
|
|
|
628
628
|
configurable: true,
|
|
629
629
|
value: 120,
|
|
630
630
|
});
|
|
631
|
+
vi.spyOn(megamenu, "getBoundingClientRect").mockReturnValue({
|
|
632
|
+
height: 120,
|
|
633
|
+
});
|
|
631
634
|
document.body.appendChild(megamenu);
|
|
632
635
|
|
|
633
636
|
Object.defineProperty(window, "scrollY", {
|
|
@@ -703,6 +706,9 @@ describe("rendering AnchorNavigation", () => {
|
|
|
703
706
|
configurable: true,
|
|
704
707
|
get: () => megamenuHeight,
|
|
705
708
|
});
|
|
709
|
+
vi.spyOn(megamenu, "getBoundingClientRect").mockImplementation(() => ({
|
|
710
|
+
height: megamenuHeight,
|
|
711
|
+
}));
|
|
706
712
|
document.body.appendChild(megamenu);
|
|
707
713
|
|
|
708
714
|
Object.defineProperty(window, "scrollY", {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
@mixin container {
|
|
27
|
+
@include typoMixins.list-unstyled;
|
|
27
28
|
@include container.base;
|
|
28
29
|
|
|
29
30
|
font-size: 0;
|
|
@@ -111,6 +112,11 @@
|
|
|
111
112
|
text-decoration: none;
|
|
112
113
|
display: inline;
|
|
113
114
|
|
|
115
|
+
&:focus-visible {
|
|
116
|
+
outline: 2px solid currentColor;
|
|
117
|
+
outline-offset: 2px;
|
|
118
|
+
}
|
|
119
|
+
|
|
114
120
|
&:hover {
|
|
115
121
|
color: var(--color-text-default);
|
|
116
122
|
text-decoration: underline;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
@use "./mixins";
|
|
2
|
+
|
|
3
|
+
// Shared selectors for the layered ODS and unlayered standalone outputs.
|
|
4
|
+
@mixin styles {
|
|
5
|
+
.osk-breadcrumbs {
|
|
6
|
+
@include mixins.base;
|
|
7
|
+
|
|
8
|
+
&__container {
|
|
9
|
+
@include mixins.container;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.osk-breadcrumbs__item {
|
|
14
|
+
@include mixins.item;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.background-contrast .osk-breadcrumbs__item,
|
|
18
|
+
.surface-contrast .osk-breadcrumbs__item,
|
|
19
|
+
.is-dark .osk-breadcrumbs__item {
|
|
20
|
+
@include mixins.item-dark;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.osk-breadcrumbs__link {
|
|
24
|
+
@include mixins.link;
|
|
25
|
+
|
|
26
|
+
&[aria-current="page"] {
|
|
27
|
+
@include mixins.link-current;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,29 +1,5 @@
|
|
|
1
|
-
@use "./
|
|
1
|
+
@use "./rules";
|
|
2
2
|
|
|
3
3
|
@layer components {
|
|
4
|
-
.
|
|
5
|
-
@include mixins.base;
|
|
6
|
-
|
|
7
|
-
&__container {
|
|
8
|
-
@include mixins.container;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.osk-breadcrumbs__item {
|
|
13
|
-
@include mixins.item;
|
|
14
|
-
|
|
15
|
-
.background-contrast &,
|
|
16
|
-
.surface-contrast &,
|
|
17
|
-
.is-dark & {
|
|
18
|
-
@include mixins.item-dark;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.osk-breadcrumbs__link {
|
|
23
|
-
@include mixins.link;
|
|
24
|
-
|
|
25
|
-
&[aria-current="page"] {
|
|
26
|
-
@include mixins.link-current;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
4
|
+
@include rules.styles;
|
|
29
5
|
}
|
|
@@ -16,10 +16,33 @@
|
|
|
16
16
|
@include visibility.visually-hidden;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
:where(button, input, select, textarea) {
|
|
20
|
+
font: inherit;
|
|
21
|
+
color: inherit;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:where(h3, strong, b) {
|
|
25
|
+
font-family: inherit;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:where(strong, b) {
|
|
29
|
+
font-weight: 700;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
li {
|
|
33
|
+
font-size: inherit;
|
|
34
|
+
line-height: inherit;
|
|
35
|
+
font-weight: inherit;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:where(a) {
|
|
20
39
|
color: var(--color-text-default);
|
|
21
40
|
text-decoration: none;
|
|
41
|
+
font-family: inherit;
|
|
42
|
+
font-weight: inherit;
|
|
22
43
|
font-size: inherit;
|
|
44
|
+
background-color: transparent;
|
|
45
|
+
box-shadow: none;
|
|
23
46
|
|
|
24
47
|
&:hover,
|
|
25
48
|
&:focus,
|
|
@@ -27,6 +50,8 @@
|
|
|
27
50
|
text-decoration: underline;
|
|
28
51
|
text-underline-offset: convert.to-rem(2px);
|
|
29
52
|
text-decoration-thickness: auto;
|
|
53
|
+
background-color: transparent;
|
|
54
|
+
box-shadow: none;
|
|
30
55
|
}
|
|
31
56
|
|
|
32
57
|
&:focus-visible {
|
|
@@ -46,6 +71,11 @@
|
|
|
46
71
|
[tabindex]:not([tabindex="-1"]),
|
|
47
72
|
[contentEditable="true"] {
|
|
48
73
|
@include base.focusring;
|
|
74
|
+
|
|
75
|
+
&:focus-visible {
|
|
76
|
+
// Legacy ODS explicitly suppresses outlines with !important.
|
|
77
|
+
outline-width: base.$focusring-width !important;
|
|
78
|
+
}
|
|
49
79
|
}
|
|
50
80
|
|
|
51
81
|
*,
|
|
@@ -74,6 +104,7 @@
|
|
|
74
104
|
|
|
75
105
|
@mixin base {
|
|
76
106
|
font-size: 1rem;
|
|
107
|
+
font-weight: 400;
|
|
77
108
|
letter-spacing: convert.to-rem(-0.1px);
|
|
78
109
|
line-height: convert.to-rem(18px);
|
|
79
110
|
color: var(--color-text-default);
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
@use "../../SocialButton/styles/mixins" as socialButtonMixins;
|
|
8
8
|
@use "../../Icon/styles/mixins" as iconMixins;
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
// Keep specificity equal in document and shadow trees, above legacy link rules.
|
|
11
|
+
:is(:root, :host) #{config.$class-root} {
|
|
11
12
|
@include mixins.globals;
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
@include megamenuMixins.dark-vars;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
|
-
#{config.$class-root} {
|
|
26
|
+
:is(:root, :host) #{config.$class-root} {
|
|
26
27
|
@include mixins.base;
|
|
27
28
|
|
|
28
29
|
&__container {
|
|
@@ -62,11 +63,13 @@
|
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
|
|
65
|
-
[data-footer-toggle][aria-expanded="false"]
|
|
66
|
+
[data-footer-toggle][aria-expanded="false"]
|
|
67
|
+
> #{config.$class-root}__accordion-icon {
|
|
66
68
|
transform: rotate(0deg);
|
|
67
69
|
}
|
|
68
70
|
|
|
69
|
-
[data-footer-toggle][aria-expanded="true"]
|
|
71
|
+
[data-footer-toggle][aria-expanded="true"]
|
|
72
|
+
> #{config.$class-root}__accordion-icon {
|
|
70
73
|
transform: rotate(180deg);
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -91,7 +94,7 @@
|
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
&__menu-section >
|
|
97
|
+
&__menu-section > #{config.$class-root}__list {
|
|
95
98
|
@include mixins.accordion-list;
|
|
96
99
|
}
|
|
97
100
|
|
|
@@ -21,7 +21,10 @@ describe("Footer standalone styles", () => {
|
|
|
21
21
|
afterAll(() => stylesheet.remove());
|
|
22
22
|
|
|
23
23
|
const styleFor = (selector) =>
|
|
24
|
-
rules.find(
|
|
24
|
+
rules.find(
|
|
25
|
+
(rule) =>
|
|
26
|
+
rule.selectorText.replaceAll(":is(:root, :host) ", "") === selector,
|
|
27
|
+
)?.style;
|
|
25
28
|
|
|
26
29
|
it("sizes social buttons and icons without global ODS styles", () => {
|
|
27
30
|
expect(styleFor(".footer .social-button")?.display).toBe("inline-flex");
|
|
@@ -54,7 +57,9 @@ describe("Footer standalone styles", () => {
|
|
|
54
57
|
);
|
|
55
58
|
expect(componentRules.length).toBeGreaterThan(0);
|
|
56
59
|
for (const rule of componentRules) {
|
|
57
|
-
for (const selector of rule.selectorText
|
|
60
|
+
for (const selector of rule.selectorText
|
|
61
|
+
.replaceAll(":is(:root, :host) ", "")
|
|
62
|
+
.split(",")) {
|
|
58
63
|
expect(selector.trim()).toMatch(/^\.footer /);
|
|
59
64
|
}
|
|
60
65
|
}
|
|
@@ -47,6 +47,7 @@ export default class Megamenu {
|
|
|
47
47
|
mousedownHandler!: () => void;
|
|
48
48
|
touchstartHandler!: () => void;
|
|
49
49
|
instanceName!: string;
|
|
50
|
+
private scrollFrameId: number | null = null;
|
|
50
51
|
|
|
51
52
|
private isModalOpen(): boolean {
|
|
52
53
|
return document.body.classList.contains(MODAL_OPEN_CLASS);
|
|
@@ -80,6 +81,7 @@ export default class Megamenu {
|
|
|
80
81
|
this.handleToggleClick = this.handleToggleClick.bind(this);
|
|
81
82
|
this.handleKeyPress = this.handleKeyPress.bind(this);
|
|
82
83
|
this.handleScroll = this.handleScroll.bind(this);
|
|
84
|
+
this.scheduleScrollUpdate = this.scheduleScrollUpdate.bind(this);
|
|
83
85
|
this.handleAccordionClick = this.handleAccordionClick.bind(this);
|
|
84
86
|
this.handleArrowNavigation = this.handleArrowNavigation.bind(this);
|
|
85
87
|
this.trapFocus = this.trapFocus.bind(this);
|
|
@@ -182,7 +184,9 @@ export default class Megamenu {
|
|
|
182
184
|
|
|
183
185
|
// Add scoped event listeners to this element
|
|
184
186
|
this.element.addEventListener("keydown", this.handleKeyPress);
|
|
185
|
-
window.addEventListener("scroll", this.
|
|
187
|
+
window.addEventListener("scroll", this.scheduleScrollUpdate, {
|
|
188
|
+
passive: true,
|
|
189
|
+
});
|
|
186
190
|
|
|
187
191
|
// Track keyboard usage for proper focus management
|
|
188
192
|
this.isKeyboardUser = false;
|
|
@@ -429,13 +433,21 @@ export default class Megamenu {
|
|
|
429
433
|
}
|
|
430
434
|
}
|
|
431
435
|
|
|
436
|
+
private scheduleScrollUpdate() {
|
|
437
|
+
if (this.scrollFrameId !== null) {
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
this.scrollFrameId = window.requestAnimationFrame(() => {
|
|
442
|
+
this.scrollFrameId = null;
|
|
443
|
+
this.handleScroll();
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
|
|
432
447
|
handleScroll() {
|
|
433
448
|
const topElement = this.element.querySelector(
|
|
434
449
|
'[data-hide-when-sticky="true"]',
|
|
435
450
|
) as HTMLElement;
|
|
436
|
-
const hasBrandMark = Boolean(
|
|
437
|
-
this.element.querySelector(BRAND_MARK_SELECTOR),
|
|
438
|
-
);
|
|
439
451
|
const effectiveScrollY = this.getEffectiveScrollY();
|
|
440
452
|
const hideThreshold = topElement?.offsetHeight || 15;
|
|
441
453
|
const shouldHideTop = effectiveScrollY > hideThreshold;
|
|
@@ -449,7 +461,10 @@ export default class Megamenu {
|
|
|
449
461
|
topElement.classList.remove("is-hidden");
|
|
450
462
|
this.element.classList.remove("top-hidden");
|
|
451
463
|
}
|
|
452
|
-
} else if (
|
|
464
|
+
} else if (
|
|
465
|
+
!this.element.classList.contains("non-sticky") &&
|
|
466
|
+
this.element.querySelector(BRAND_MARK_SELECTOR)
|
|
467
|
+
) {
|
|
453
468
|
this.element.classList.toggle("top-hidden", shouldHideTop);
|
|
454
469
|
}
|
|
455
470
|
}
|
|
@@ -775,7 +790,11 @@ export default class Megamenu {
|
|
|
775
790
|
});
|
|
776
791
|
|
|
777
792
|
this.element.removeEventListener("keydown", this.handleKeyPress);
|
|
778
|
-
window.removeEventListener("scroll", this.
|
|
793
|
+
window.removeEventListener("scroll", this.scheduleScrollUpdate);
|
|
794
|
+
if (this.scrollFrameId !== null) {
|
|
795
|
+
window.cancelAnimationFrame(this.scrollFrameId);
|
|
796
|
+
this.scrollFrameId = null;
|
|
797
|
+
}
|
|
779
798
|
|
|
780
799
|
// Remove keyboard tracking event listeners
|
|
781
800
|
this.element.removeEventListener("keydown", this.keydownHandler);
|