@orangesk/orange-design-system 2.0.0-beta.43 → 2.0.0-beta.45

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 (60) hide show
  1. package/build/components/BodyBanner/style.css +1 -1
  2. package/build/components/BodyBanner/style.css.map +1 -1
  3. package/build/components/Breadcrumbs/style.css +1 -1
  4. package/build/components/Breadcrumbs/style.css.map +1 -1
  5. package/build/components/Carousel/style.css +1 -1
  6. package/build/components/Carousel/style.css.map +1 -1
  7. package/build/components/Expander/style.css +1 -1
  8. package/build/components/Expander/style.css.map +1 -1
  9. package/build/components/Footer/style.css +1 -1
  10. package/build/components/Footer/style.css.map +1 -1
  11. package/build/components/Grid/style.css +1 -1
  12. package/build/components/Grid/style.css.map +1 -1
  13. package/build/components/Megamenu/style.css +1 -1
  14. package/build/components/Megamenu/style.css.map +1 -1
  15. package/build/components/Tag/style.css +1 -1
  16. package/build/components/Tag/style.css.map +1 -1
  17. package/build/components/index.js +1 -1
  18. package/build/components/index.js.map +1 -1
  19. package/build/components/tsconfig.tsbuildinfo +1 -1
  20. package/build/components/types/index.d.ts +4 -2
  21. package/build/components/types/src/components/Carousel/Carousel.static.d.ts +7 -0
  22. package/build/components/types/src/components/Expander/Expander.d.ts +2 -0
  23. package/build/components/types/src/components/Grid/Grid.d.ts +2 -2
  24. package/build/lib/base.css +1 -1
  25. package/build/lib/base.css.map +1 -1
  26. package/build/lib/components.css +1 -1
  27. package/build/lib/components.css.map +1 -1
  28. package/build/lib/footer.css +1 -1
  29. package/build/lib/footer.css.map +1 -1
  30. package/build/lib/megamenu.css +1 -1
  31. package/build/lib/megamenu.css.map +1 -1
  32. package/build/lib/scripts.js +1 -1
  33. package/build/lib/scripts.js.map +1 -1
  34. package/build/lib/style.css +1 -1
  35. package/build/lib/style.css.map +1 -1
  36. package/build/search-index.json +2 -2
  37. package/build/sprite.svg +1 -1
  38. package/package.json +7 -7
  39. package/src/assets/icons/pictogram-internet--dark.svg +15 -0
  40. package/src/assets/icons/pictogram-internet.svg +15 -0
  41. package/src/assets/icons/pictogram-my-orange--dark.svg +6 -0
  42. package/src/assets/icons/pictogram-my-orange.svg +6 -0
  43. package/src/assets/icons/pictogram-tariffs--dark.svg +9 -0
  44. package/src/assets/icons/pictogram-tariffs.svg +9 -0
  45. package/src/components/BodyBanner/styles/mixins.scss +2 -12
  46. package/src/components/Carousel/Carousel.static.ts +182 -67
  47. package/src/components/Carousel/styles/mixins.scss +7 -2
  48. package/src/components/Carousel/tests/Carousel.static.test.jsx +178 -5
  49. package/src/components/Expander/Expander.tsx +4 -0
  50. package/src/components/Expander/styles/style.scss +12 -0
  51. package/src/components/Expander/tests/Expander.conformance.test.jsx +4 -0
  52. package/src/components/Expander/tests/Expander.unit.test.jsx +9 -0
  53. package/src/components/Grid/Grid.tsx +5 -2
  54. package/src/components/Grid/styles/config.scss +3 -2
  55. package/src/components/Grid/tests/Grid.unit.test.jsx +40 -10
  56. package/src/components/Tag/styles/config.scss +5 -1
  57. package/src/components/Tag/styles/mixins.scss +2 -1
  58. package/src/styles/base/globals.scss +1 -0
  59. package/src/styles/export/base.js +1 -1
  60. package/src/styles/tokens/base.scss +1 -1
@@ -124,6 +124,12 @@ describe("Carousel Static - External Controls", () => {
124
124
  });
125
125
 
126
126
  describe("External Controls Initialization", () => {
127
+ it("should disable a11y scrollOnFocus to prevent focus-triggered slide jumps", () => {
128
+ const swiperConfig = Swiper.mock.calls[0]?.[1];
129
+
130
+ expect(swiperConfig?.a11y?.scrollOnFocus).toBe(false);
131
+ });
132
+
127
133
  it("should find and initialize external controls", () => {
128
134
  const prevButton = document.getElementById("prev-btn");
129
135
  const nextButton = document.getElementById("next-btn");
@@ -691,7 +697,76 @@ describe("Carousel Static - Auto-Disable Feature", () => {
691
697
  });
692
698
  });
693
699
 
694
- it("should use right inset for bleed-right trailing offset", () => {
700
+ it("should disable bleed-right when slides fit wrapper despite right inset", () => {
701
+ const originalInnerWidth = window.innerWidth;
702
+ Object.defineProperty(window, "innerWidth", {
703
+ configurable: true,
704
+ writable: true,
705
+ value: 1200,
706
+ });
707
+
708
+ mockSwiperInstance.slides = [
709
+ document.createElement("div"),
710
+ document.createElement("div"),
711
+ ];
712
+ mockSwiperInstance.params.slidesPerView = 2;
713
+
714
+ document.body.innerHTML = `
715
+ <div class="carousel carousel--bleed-right" data-carousel-id="test-carousel" id="test-carousel">
716
+ <div class="carousel__viewport-wrapper">
717
+ <div class="carousel__viewport">
718
+ <div class="carousel__track">
719
+ <div class="carousel__slide">Slide 1</div>
720
+ <div class="carousel__slide">Slide 2</div>
721
+ </div>
722
+ </div>
723
+ </div>
724
+ <div class="carousel__pagination"></div>
725
+ </div>
726
+ `;
727
+
728
+ carouselElement = document.querySelector(".carousel");
729
+ const viewportWrapper = carouselElement.querySelector(
730
+ ".carousel__viewport-wrapper",
731
+ );
732
+ const track = carouselElement.querySelector(".carousel__track");
733
+
734
+ Object.defineProperty(viewportWrapper, "clientWidth", {
735
+ configurable: true,
736
+ value: 900,
737
+ });
738
+ Object.defineProperty(track, "scrollWidth", {
739
+ configurable: true,
740
+ value: 900,
741
+ });
742
+ Object.defineProperty(viewportWrapper, "getBoundingClientRect", {
743
+ configurable: true,
744
+ value: () => ({
745
+ top: 0,
746
+ right: 1000,
747
+ bottom: 200,
748
+ left: 100,
749
+ width: 900,
750
+ height: 200,
751
+ x: 100,
752
+ y: 0,
753
+ toJSON: () => ({}),
754
+ }),
755
+ });
756
+
757
+ carouselInstance = new Carousel(carouselElement);
758
+
759
+ expect(mockSwiperInstance.params.slidesOffsetBefore).toBe(0);
760
+ expect(mockSwiperInstance.params.slidesOffsetAfter).toBe(0);
761
+
762
+ Object.defineProperty(window, "innerWidth", {
763
+ configurable: true,
764
+ writable: true,
765
+ value: originalInnerWidth,
766
+ });
767
+ });
768
+
769
+ it("should keep wrapper-based bleed geometry without offsets", () => {
695
770
  const originalInnerWidth = window.innerWidth;
696
771
  Object.defineProperty(window, "innerWidth", {
697
772
  configurable: true,
@@ -726,6 +801,16 @@ describe("Carousel Static - Auto-Disable Feature", () => {
726
801
  const viewportWrapper = carouselElement.querySelector(
727
802
  ".carousel__viewport-wrapper",
728
803
  );
804
+ const track = carouselElement.querySelector(".carousel__track");
805
+
806
+ Object.defineProperty(viewportWrapper, "clientWidth", {
807
+ configurable: true,
808
+ value: 800,
809
+ });
810
+ Object.defineProperty(track, "scrollWidth", {
811
+ configurable: true,
812
+ value: 1200,
813
+ });
729
814
 
730
815
  Object.defineProperty(viewportWrapper, "getBoundingClientRect", {
731
816
  configurable: true,
@@ -744,16 +829,17 @@ describe("Carousel Static - Auto-Disable Feature", () => {
744
829
 
745
830
  carouselInstance = new Carousel(carouselElement);
746
831
 
747
- expect(mockSwiperInstance.params.slidesOffsetBefore).toBe(120);
748
- expect(mockSwiperInstance.params.slidesOffsetAfter).toBe(80);
832
+ expect(mockSwiperInstance.params.slidesOffsetBefore).toBe(0);
833
+ expect(mockSwiperInstance.params.slidesOffsetAfter).toBe(0);
834
+ expect(mockSwiperInstance.params.width).toBe(800);
749
835
  expect(
750
836
  carouselElement.style.getPropertyValue(
751
837
  "--carousel-bleed-viewport-width",
752
838
  ),
753
- ).toBe("1000px");
839
+ ).toBe("880px");
754
840
  expect(
755
841
  carouselElement.style.getPropertyValue("--carousel-bleed-margin-left"),
756
- ).toBe("-120px");
842
+ ).toBe("120px");
757
843
 
758
844
  Object.defineProperty(window, "innerWidth", {
759
845
  configurable: true,
@@ -761,5 +847,92 @@ describe("Carousel Static - Auto-Disable Feature", () => {
761
847
  value: originalInnerWidth,
762
848
  });
763
849
  });
850
+
851
+ it("should calculate bleed-right scrollbar drag from logical viewport, not shell width", () => {
852
+ mockSwiperInstance.slides = [
853
+ document.createElement("div"),
854
+ document.createElement("div"),
855
+ document.createElement("div"),
856
+ ];
857
+ mockSwiperInstance.slides.forEach((slide) => {
858
+ Object.defineProperty(slide, "offsetWidth", {
859
+ configurable: true,
860
+ value: 300,
861
+ });
862
+ });
863
+
864
+ mockSwiperInstance.params.slidesPerView = 1.2;
865
+ mockSwiperInstance.params.spaceBetween = 0;
866
+ mockSwiperInstance.width = 800;
867
+ mockSwiperInstance.progress = 0.5;
868
+ mockSwiperInstance.minTranslate = vi.fn(() => -300);
869
+ mockSwiperInstance.maxTranslate = vi.fn(() => 0);
870
+
871
+ const scrollbarEl = document.createElement("div");
872
+ const dragEl = document.createElement("div");
873
+ Object.defineProperty(scrollbarEl, "offsetWidth", {
874
+ configurable: true,
875
+ value: 200,
876
+ });
877
+
878
+ mockSwiperInstance.scrollbar = {
879
+ updateSize: vi.fn(),
880
+ el: scrollbarEl,
881
+ dragEl,
882
+ };
883
+
884
+ document.body.innerHTML = `
885
+ <div class="carousel carousel--bleed-right" data-carousel-id="test-carousel" id="test-carousel">
886
+ <div class="carousel__viewport-wrapper">
887
+ <div class="carousel__viewport">
888
+ <div class="carousel__track">
889
+ <div class="carousel__slide">Slide 1</div>
890
+ <div class="carousel__slide">Slide 2</div>
891
+ <div class="carousel__slide">Slide 3</div>
892
+ </div>
893
+ </div>
894
+ </div>
895
+ <div class="carousel__pagination"></div>
896
+ </div>
897
+ `;
898
+
899
+ carouselElement = document.querySelector(".carousel");
900
+ const viewportWrapper = carouselElement.querySelector(
901
+ ".carousel__viewport-wrapper",
902
+ );
903
+ const track = carouselElement.querySelector(".carousel__track");
904
+
905
+ Object.defineProperty(carouselElement, "clientWidth", {
906
+ configurable: true,
907
+ value: 800,
908
+ });
909
+ Object.defineProperty(viewportWrapper, "clientWidth", {
910
+ configurable: true,
911
+ value: 1000,
912
+ });
913
+ Object.defineProperty(track, "scrollWidth", {
914
+ configurable: true,
915
+ value: 900,
916
+ });
917
+ Object.defineProperty(viewportWrapper, "getBoundingClientRect", {
918
+ configurable: true,
919
+ value: () => ({
920
+ top: 0,
921
+ right: 1120,
922
+ bottom: 200,
923
+ left: 120,
924
+ width: 1000,
925
+ height: 200,
926
+ x: 120,
927
+ y: 0,
928
+ toJSON: () => ({}),
929
+ }),
930
+ });
931
+
932
+ carouselInstance = new Carousel(carouselElement);
933
+
934
+ // Regression: drag must not become full width just because shell wrapper is wider than logical viewport.
935
+ expect(dragEl.style.width).not.toBe("200px");
936
+ });
764
937
  });
765
938
  });
@@ -25,6 +25,8 @@ interface ExpanderProps {
25
25
  children?: React.ReactNode;
26
26
  /** Expander takes full width of its container */
27
27
  isFullWidth?: boolean;
28
+ /** Position of trigger relative to content when opened */
29
+ placement?: "top" | "bottom";
28
30
  /** Group identifier for syncing multiple expanders together */
29
31
  toggleGroup?: string;
30
32
  /** Initial open state */
@@ -40,6 +42,7 @@ export const Expander: React.FC<ExpanderProps> = (props) => {
40
42
  renderSummary,
41
43
  renderSummaryOpened,
42
44
  isFullWidth,
45
+ placement = "bottom",
43
46
  toggleGroup,
44
47
  ...other
45
48
  } = props;
@@ -49,6 +52,7 @@ export const Expander: React.FC<ExpanderProps> = (props) => {
49
52
  CLASS_ROOT,
50
53
  {
51
54
  [`${CLASS_ROOT}--fullwidth`]: isFullWidth,
55
+ [`${CLASS_ROOT}--placement-top`]: placement === "top",
52
56
  },
53
57
  className,
54
58
  );
@@ -51,6 +51,18 @@
51
51
  }
52
52
  }
53
53
 
54
+ &--placement-top {
55
+ &[open] {
56
+ display: flex;
57
+ flex-direction: column-reverse;
58
+
59
+ summary {
60
+ margin-top: space.get("large");
61
+ margin-bottom: 0;
62
+ }
63
+ }
64
+ }
65
+
54
66
  &[open] {
55
67
  svg[data-summary-icon] {
56
68
  transform: rotate(180deg) !important;
@@ -47,6 +47,10 @@ const example = (
47
47
  >
48
48
  Content
49
49
  </Expander>
50
+
51
+ <Expander summary="Open above trigger" placement="top">
52
+ Content
53
+ </Expander>
50
54
  </>
51
55
  );
52
56
 
@@ -184,4 +184,13 @@ describe("Expander", () => {
184
184
  );
185
185
  expect(getByTestId("test-id")).toHaveClass("expander--fullwidth");
186
186
  });
187
+
188
+ it("applies placement-top class when placement prop is top", () => {
189
+ const { getByTestId } = render(
190
+ <Expander data-testid="test-id" summary="Show details" placement="top">
191
+ Content
192
+ </Expander>,
193
+ );
194
+ expect(getByTestId("test-id")).toHaveClass("expander--placement-top");
195
+ });
187
196
  });
@@ -5,17 +5,20 @@ import { genResponsiveClasses } from "../../utils";
5
5
  export type GridVAlign = "stretch" | "start" | "end" | "center";
6
6
  export type GridHAlign = "end" | "center" | "space-around" | "space-between";
7
7
  export type GridRowGapSize =
8
+ | "none"
9
+ | "xsmall"
8
10
  | "small"
9
11
  | "medium"
10
12
  | "large"
11
13
  | "xlarge"
12
- | Record<string, "small" | "medium" | "large" | "xlarge">;
14
+ | Record<string, "none" | "xsmall" | "small" | "medium" | "large" | "xlarge">;
13
15
  export type GridColumnGapSize =
14
16
  | "none"
15
17
  | "small"
16
18
  | "default"
17
19
  | "large"
18
- | Record<string, "none" | "small" | "default" | "large">;
20
+ | "xlarge"
21
+ | Record<string, "none" | "small" | "default" | "large" | "xlarge">;
19
22
 
20
23
  export interface GridProps extends React.HTMLAttributes<HTMLElement> {
21
24
  vAlign?: GridVAlign;
@@ -2,12 +2,13 @@
2
2
 
3
3
  $grid-base: 12 !default;
4
4
 
5
- $grid-row-gap-sizes: ("small", "medium", "large", "xlarge");
6
- $grid-column-gap-sizes: ("none", "small", "default", "large");
5
+ $grid-row-gap-sizes: ("none", "xsmall", "small", "medium", "large", "xlarge");
6
+ $grid-column-gap-sizes: ("none", "small", "default", "large", "xlarge");
7
7
 
8
8
  $column-gap: (
9
9
  none: 0,
10
10
  small: space.get("xsmall"),
11
11
  default: space.get("small"),
12
12
  large: space.get("medium"),
13
+ xlarge: space.get("large"),
13
14
  );
@@ -52,16 +52,20 @@ describe("Grid", () => {
52
52
  expect(getByTestId("test-id")).toHaveClass("grid--justify-height");
53
53
  });
54
54
 
55
- ["medium", "large", "xlarge"].forEach((rowGapSize) => {
56
- it(`applies grid-row-gap--${rowGapSize} class when rowGapSize is ${rowGapSize}`, () => {
57
- const { getByTestId } = render(
58
- <Grid data-testid="test-id" rowGapSize={rowGapSize} />,
59
- );
60
- expect(getByTestId("test-id")).toHaveClass(`grid-row-gap--${rowGapSize}`);
61
- });
62
- });
63
-
64
- ["small", "large", "none"].forEach((columnGapSize) => {
55
+ ["none", "xsmall", "small", "medium", "large", "xlarge"].forEach(
56
+ (rowGapSize) => {
57
+ it(`applies grid-row-gap--${rowGapSize} class when rowGapSize is ${rowGapSize}`, () => {
58
+ const { getByTestId } = render(
59
+ <Grid data-testid="test-id" rowGapSize={rowGapSize} />,
60
+ );
61
+ expect(getByTestId("test-id")).toHaveClass(
62
+ `grid-row-gap--${rowGapSize}`,
63
+ );
64
+ });
65
+ },
66
+ );
67
+
68
+ ["small", "large", "xlarge", "none"].forEach((columnGapSize) => {
65
69
  it(`applies grid-column-gap--${columnGapSize} class when columnGapSize is ${columnGapSize}`, () => {
66
70
  const { getByTestId } = render(
67
71
  <Grid data-testid="test-id" columnGapSize={columnGapSize} />,
@@ -72,6 +76,32 @@ describe("Grid", () => {
72
76
  });
73
77
  });
74
78
 
79
+ it("applies responsive row gap classes when rowGapSize is object", () => {
80
+ const { getByTestId } = render(
81
+ <Grid
82
+ data-testid="test-id"
83
+ rowGapSize={{ xs: "medium", md: "xlarge" }}
84
+ />,
85
+ );
86
+ expect(getByTestId("test-id")).toHaveClass(
87
+ "grid-row-gap--medium",
88
+ "grid-row-gap--md-xlarge",
89
+ );
90
+ });
91
+
92
+ it("applies responsive column gap classes when columnGapSize is object", () => {
93
+ const { getByTestId } = render(
94
+ <Grid
95
+ data-testid="test-id"
96
+ columnGapSize={{ xs: "small", lg: "xlarge" }}
97
+ />,
98
+ );
99
+ expect(getByTestId("test-id")).toHaveClass(
100
+ "grid-column-gap--small",
101
+ "grid-column-gap--lg-xlarge",
102
+ );
103
+ });
104
+
75
105
  it("merges additional className", () => {
76
106
  const { getByTestId } = render(
77
107
  <Grid data-testid="test-id" className="test-class" />,
@@ -15,18 +15,21 @@ $sizes: (
15
15
  font-size: convert.to-rem(14px) "!important",
16
16
  line-height: 1rem "!important",
17
17
  font-weight: 700,
18
+ border-width: 1px,
18
19
  ),
19
20
  small: (
20
21
  padding: convert.to-rem(2px) convert.to-rem(8px),
21
22
  font-size: convert.to-rem(12px) "!important",
22
23
  line-height: convert.to-rem(14px) "!important",
23
24
  font-weight: 400,
25
+ border-width: 2px,
24
26
  ),
25
27
  large: (
26
28
  padding: convert.to-rem(11px) convert.to-rem(15px),
27
29
  font-size: convert.to-rem(16px) "!important",
28
30
  line-height: convert.to-rem(18px) "!important",
29
31
  font-weight: 700,
32
+ border-width: 2px,
30
33
  ),
31
34
  );
32
35
 
@@ -83,7 +86,8 @@ $colors: (
83
86
  "transparent": (
84
87
  background-color: transparent,
85
88
  color: var(--color-text-default),
86
- border: 1px solid var(--color-border-strong),
89
+ border-color: var(--color-border-strong),
90
+ border-style: solid,
87
91
  ),
88
92
  );
89
93
 
@@ -19,7 +19,8 @@
19
19
  }
20
20
 
21
21
  @mixin color-transparent() {
22
- border: 1px solid var(--color-border-strong);
22
+ border-color: var(--color-border-strong);
23
+ border-style: solid;
23
24
  }
24
25
 
25
26
  @mixin buttton-disabled($is-icon: false) {
@@ -31,6 +31,7 @@ html,
31
31
  body {
32
32
  padding: 0;
33
33
  margin: 0;
34
+ -webkit-text-size-adjust: 100%;
34
35
  text-size-adjust: 100%;
35
36
  }
36
37
 
@@ -2,7 +2,7 @@
2
2
  // Do not edit this file directly - edit the SCSS source instead
3
3
 
4
4
  export const exports = {
5
- "font-family": "OrangeSK Neue, Arial, Helvetica Neue, sans-serif",
5
+ "font-family": "OrangeSK Neue, Helvetica Neue, Helvetica, Arial, sans-serif",
6
6
  "font-size": "16px",
7
7
  "line-height": "1.25",
8
8
  "background": "var(--color-background-primary)",
@@ -1,7 +1,7 @@
1
1
  @use "sass:color" as sasscolor;
2
2
  @use "./color";
3
3
 
4
- $font-family: "OrangeSK Neue", Arial, "Helvetica Neue", sans-serif;
4
+ $font-family: "OrangeSK Neue", "Helvetica Neue", Helvetica, Arial, sans-serif;
5
5
  $font-size: 16px;
6
6
  $line-height: 1.25;
7
7