@orangesk/orange-design-system 3.10.0 → 3.12.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.
Files changed (52) hide show
  1. package/build/components/Carousel/style.css +1 -1
  2. package/build/components/Carousel/style.css.map +1 -1
  3. package/build/components/Megamenu/style.css +1 -1
  4. package/build/components/Megamenu/style.css.map +1 -1
  5. package/build/components/index.js +1 -1
  6. package/build/components/index.js.map +1 -1
  7. package/build/footer-sprite-dark.svg +1 -0
  8. package/build/footer-sprite-light.svg +1 -0
  9. package/build/lib/components.css +1 -1
  10. package/build/lib/components.css.map +1 -1
  11. package/build/lib/megamenu.css +1 -1
  12. package/build/lib/megamenu.css.map +1 -1
  13. package/build/lib/scripts.js +1 -1
  14. package/build/lib/scripts.js.map +1 -1
  15. package/build/lib/style.css +1 -1
  16. package/build/lib/style.css.map +1 -1
  17. package/package.json +26 -26
  18. package/public/footer-sprite-dark.svg +1 -0
  19. package/public/footer-sprite-light.svg +1 -0
  20. package/src/assets/footer/appstore.svg +31 -0
  21. package/src/assets/footer/googleplay.svg +52 -0
  22. package/src/assets/footer/logo.svg +33 -0
  23. package/src/{components/Footer/PlanObnovy.tsx → assets/footer/plan-obnovy.svg} +53 -211
  24. package/src/assets/icons/age-rating-3.svg +0 -0
  25. package/src/assets/icons/assistent.svg +0 -0
  26. package/src/assets/icons/boxes.svg +0 -0
  27. package/src/assets/icons/business-lounge.svg +0 -0
  28. package/src/assets/icons/calendar-30.svg +0 -0
  29. package/src/assets/icons/calendar-month.svg +0 -0
  30. package/src/assets/icons/communication-settings.svg +0 -0
  31. package/src/assets/icons/cookies.svg +0 -0
  32. package/src/assets/icons/currency-euro.svg +0 -0
  33. package/src/assets/icons/data-services.svg +0 -0
  34. package/src/assets/icons/device-mobile-package.svg +0 -0
  35. package/src/assets/icons/futher-education.svg +0 -0
  36. package/src/assets/icons/modifier-delete.svg +0 -0
  37. package/src/assets/icons/orange-experts-orange-business-consultant.svg +0 -0
  38. package/src/assets/icons/orange-messenger.svg +0 -0
  39. package/src/assets/icons/orange-reflect.svg +0 -0
  40. package/src/assets/icons/personal-smartphone-trainer.svg +0 -0
  41. package/src/assets/icons/unlimited-calls.svg +0 -0
  42. package/src/components/Carousel/Carousel.static.ts +67 -16
  43. package/src/components/Carousel/styles/mixins.scss +8 -7
  44. package/src/components/Carousel/tests/Carousel.interactions.test.ts +102 -0
  45. package/src/components/Carousel/tests/Carousel.lifecycle.test.ts +223 -0
  46. package/src/components/CarouselHero/CarouselHero.static.ts +3 -0
  47. package/src/components/CarouselPromotions/CarouselPromotions.static.ts +3 -0
  48. package/src/components/Footer/Footer.tsx +44 -54
  49. package/src/components/Footer/FooterIcon.tsx +12 -0
  50. package/src/components/Footer/data.ts +4 -2
  51. package/src/components/Footer/tests/Footer.unit.test.jsx +63 -0
  52. package/src/components/Megamenu/styles/mixins.scss +2 -0
@@ -1,6 +1,5 @@
1
1
  import cx from "classnames";
2
2
  import React from "react";
3
- import { SocialButton } from "../SocialButton";
4
3
  import {
5
4
  CLASS_ACCORDION_ICON,
6
5
  CLASS_ACCORDION_TOGGLE,
@@ -24,15 +23,26 @@ import {
24
23
  CLASS_TITLE,
25
24
  } from "./constants";
26
25
  import footerData, { apps, socials } from "./data";
27
- import { PlanObnovyImage } from "./PlanObnovy";
26
+ import { FooterIcon } from "./FooterIcon";
28
27
 
29
28
  interface FooterProps extends React.HTMLAttributes<HTMLDivElement> {
30
29
  data?: typeof footerData;
31
30
  className?: string;
31
+ /** Override the theme sprite URL for a custom hosting location. */
32
+ spritePath?: string;
32
33
  }
33
34
 
34
- const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
35
+ const Footer: React.FC<FooterProps> = ({
36
+ className,
37
+ data = footerData,
38
+ spritePath,
39
+ }) => {
35
40
  const accordionIdPrefix = `footer-${React.useId().replace(/:/g, "")}`;
41
+ const themeSpritePath =
42
+ spritePath ??
43
+ (className?.split(/\s+/).includes("is-dark")
44
+ ? "/footer-sprite-dark.svg"
45
+ : "/footer-sprite-light.svg");
36
46
 
37
47
  return (
38
48
  <footer className={cx(CLASS_ROOT, className)} data-footer>
@@ -43,45 +53,12 @@ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
43
53
  aria-label="Odkaz na úvodnú stránku"
44
54
  className={CLASS_LOGO}
45
55
  >
46
- <svg
56
+ <FooterIcon
57
+ name="logo"
58
+ spritePath={themeSpritePath}
47
59
  width="48"
48
60
  height="48"
49
- viewBox="0 0 48 48"
50
- fill="none"
51
- xmlns="http://www.w3.org/2000/svg"
52
- >
53
- <path d="M48 0H0V48H48V0Z" fill="black" />
54
- <path
55
- fillRule="evenodd"
56
- clipRule="evenodd"
57
- d="M48 48H0V0H48V48Z"
58
- fill="#FF7900"
59
- />
60
- <path
61
- 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"
62
- fill="white"
63
- />
64
- <path
65
- fillRule="evenodd"
66
- clipRule="evenodd"
67
- 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"
68
- fill="white"
69
- />
70
- <path
71
- 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"
72
- fill="white"
73
- />
74
- <path
75
- fillRule="evenodd"
76
- clipRule="evenodd"
77
- 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"
78
- fill="white"
79
- />
80
- <path
81
- 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"
82
- fill="white"
83
- />
84
- </svg>
61
+ />
85
62
  </a>
86
63
  <ul
87
64
  className={cx(
@@ -94,11 +71,17 @@ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
94
71
  <li className={CLASS_LIST_BREAK_SM_DOWN} aria-hidden="true" />
95
72
  {socials.map((social, index) => (
96
73
  <li key={`footer-social-link-${index}`}>
97
- <SocialButton
98
- name={social.name}
74
+ <a
75
+ className={`social-button social-button--${social.name}`}
99
76
  href={social.url}
100
77
  aria-label={social.label}
101
- />
78
+ >
79
+ <FooterIcon
80
+ name={social.name}
81
+ spritePath={themeSpritePath}
82
+ className="icon icon--medium"
83
+ />
84
+ </a>
102
85
  </li>
103
86
  ))}
104
87
  </ul>
@@ -122,17 +105,12 @@ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
122
105
  >
123
106
  <span className={CLASS_TITLE}>{column.title}</span>
124
107
  <span className={CLASS_ACCORDION_ICON} aria-hidden="true">
125
- <svg
108
+ <FooterIcon
109
+ name="chevron-down"
110
+ spritePath={themeSpritePath}
126
111
  width="24"
127
112
  height="24"
128
- viewBox="0 0 80 80"
129
- xmlns="http://www.w3.org/2000/svg"
130
- >
131
- <path
132
- d="M66.666 33.333 40 60 13.333 33.333 20 26.667l20 20 20-20 6.666 6.666Z"
133
- fill="currentColor"
134
- />
135
- </svg>
113
+ />
136
114
  </span>
137
115
  </button>
138
116
  <ul
@@ -166,7 +144,14 @@ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
166
144
  {apps.map((app, index) => (
167
145
  <li key={`footer-app-link-${index}`}>
168
146
  <a href={app.url} target="_blank" rel="noopener noreferrer">
169
- <img src={app.src} alt={app.label} />
147
+ <FooterIcon
148
+ name={app.icon}
149
+ spritePath={themeSpritePath}
150
+ width={app.width}
151
+ height={40}
152
+ role="img"
153
+ aria-label={app.label}
154
+ />
170
155
  </a>
171
156
  </li>
172
157
  ))}
@@ -176,7 +161,12 @@ const Footer: React.FC<FooterProps> = ({ className, data = footerData }) => {
176
161
  href="https://www.orange.sk/orange-slovensko/plan-obnovy"
177
162
  aria-label="Plán obnovy"
178
163
  >
179
- <PlanObnovyImage />
164
+ <FooterIcon
165
+ name="plan-obnovy"
166
+ spritePath={themeSpritePath}
167
+ width="260"
168
+ height="60"
169
+ />
180
170
  </a>
181
171
  </div>
182
172
 
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+
3
+ interface FooterIconProps extends React.SVGAttributes<SVGSVGElement> {
4
+ name: string;
5
+ spritePath: string;
6
+ }
7
+
8
+ export const FooterIcon = ({ name, spritePath, ...other }: FooterIconProps) => (
9
+ <svg aria-hidden={other["aria-label"] ? undefined : "true"} {...other}>
10
+ <use xlinkHref={`${spritePath}#${name}`} />
11
+ </svg>
12
+ );
@@ -102,12 +102,14 @@ export const socials: Array<{ name: SocialName; url: string; label: string }> =
102
102
  export const apps = [
103
103
  {
104
104
  label: "App Store",
105
- src: "/appstore.svg",
105
+ icon: "appstore",
106
+ width: 120,
106
107
  url: "https://apps.apple.com/sk/app/m%C3%B4j-orange/id519421813",
107
108
  },
108
109
  {
109
110
  label: "Google Play",
110
- src: "/googleplay.svg",
111
+ icon: "googleplay",
112
+ width: 135,
111
113
  url: "https://play.google.com/store/apps/details?id=sk.orange.android.orangego",
112
114
  },
113
115
  ];
@@ -1,8 +1,71 @@
1
+ import { readFileSync } from "node:fs";
1
2
  import { render } from "@testing-library/react";
2
3
  import footerData from "../data";
3
4
  import { Footer } from "../Footer";
4
5
 
5
6
  describe("Footer", () => {
7
+ it.each([
8
+ [undefined, "/footer-sprite-light.svg"],
9
+ ["custom-footer is-dark", "/footer-sprite-dark.svg"],
10
+ ])("uses a complete standalone sprite for %s", (className, spritePath) => {
11
+ const { container } = render(<Footer className={className} />);
12
+ const sprite = new DOMParser().parseFromString(
13
+ readFileSync(`public${spritePath}`, "utf8"),
14
+ "image/svg+xml",
15
+ );
16
+ expect(sprite.querySelector("parsererror")).toBeNull();
17
+ expect(sprite.querySelectorAll("symbol")).toHaveLength(10);
18
+ const references = Array.from(container.querySelectorAll("use"));
19
+ expect(references).toHaveLength(13);
20
+ for (const reference of references) {
21
+ const href = reference.getAttribute("xlink:href");
22
+ expect(href).toMatch(new RegExp(`^${spritePath}#`));
23
+ expect(sprite.getElementById(href.split("#")[1])).not.toBeNull();
24
+ }
25
+ expect(container.querySelector("img, path")).toBeNull();
26
+ for (const element of sprite.querySelectorAll("[clip-path]")) {
27
+ const id = element
28
+ .getAttribute("clip-path")
29
+ .match(/url\(#([^)]+)\)/)?.[1];
30
+ expect(sprite.getElementById(id)).not.toBeNull();
31
+ }
32
+ });
33
+
34
+ it("supports a custom sprite hosting URL", () => {
35
+ const { container } = render(<Footer spritePath="/assets/footer.svg" />);
36
+ for (const reference of container.querySelectorAll("use")) {
37
+ expect(reference.getAttribute("xlink:href")).toMatch(
38
+ /^\/assets\/footer\.svg#/,
39
+ );
40
+ }
41
+ });
42
+
43
+ it("keeps social interaction colors and fixes theme colors in each sprite", () => {
44
+ for (const [theme, color] of [
45
+ ["light", "#000000"],
46
+ ["dark", "#ffffff"],
47
+ ]) {
48
+ const sprite = new DOMParser().parseFromString(
49
+ readFileSync(`public/footer-sprite-${theme}.svg`, "utf8"),
50
+ "image/svg+xml",
51
+ );
52
+ for (const name of ["chevron-down", "plan-obnovy"]) {
53
+ const symbol = sprite.getElementById(name);
54
+ expect(symbol.outerHTML).not.toContain("currentColor");
55
+ const colors = [
56
+ symbol.getAttribute("fill"),
57
+ ...Array.from(symbol.querySelectorAll("[fill]"), (element) =>
58
+ element.getAttribute("fill"),
59
+ ),
60
+ ];
61
+ expect(colors).toContain(color === "#000000" ? "#000" : "#fff");
62
+ }
63
+ expect(sprite.getElementById("facebook-2").outerHTML).toContain(
64
+ "currentColor",
65
+ );
66
+ }
67
+ });
68
+
6
69
  it("renders without crashing", () => {
7
70
  const { getByRole } = render(<Footer />);
8
71
  // Should render a footer landmark
@@ -659,7 +659,9 @@
659
659
 
660
660
  @mixin subnav-item {
661
661
  display: flex;
662
+ flex-wrap: wrap;
662
663
  column-gap: convert.to-rem(10px);
664
+ row-gap: convert.to-rem(5px);
663
665
  margin-bottom: convert.to-rem(10px) !important;
664
666
 
665
667
  > #{config.$class-root}__tag {