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

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 (73) hide show
  1. package/build/components/Breadcrumbs/style.css +1 -1
  2. package/build/components/Breadcrumbs/style.css.map +1 -1
  3. package/build/components/Carousel/style.css +1 -1
  4. package/build/components/Carousel/style.css.map +1 -1
  5. package/build/components/Footer/style.css +1 -1
  6. package/build/components/Footer/style.css.map +1 -1
  7. package/build/components/Grid/style.css +1 -1
  8. package/build/components/Grid/style.css.map +1 -1
  9. package/build/components/Link/style.css +1 -1
  10. package/build/components/Link/style.css.map +1 -1
  11. package/build/components/Megamenu/style.css +1 -1
  12. package/build/components/Megamenu/style.css.map +1 -1
  13. package/build/components/Stepbar/style.css +1 -1
  14. package/build/components/Stepbar/style.css.map +1 -1
  15. package/build/components/Tabs/style.css +1 -1
  16. package/build/components/Tabs/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 +1 -4
  21. package/build/components/types/src/components/CarouselHero/CarouselHero.d.ts +1 -0
  22. package/build/components/types/src/components/Preview/CodeExample.d.ts +1 -0
  23. package/build/components/types/src/components/Preview/PreviewGenerator.d.ts +1 -0
  24. package/build/components/types/src/components/Preview/getElementDisplayName.d.ts +1 -0
  25. package/build/components/types/src/components/Tabs/Tabs.d.ts +0 -4
  26. package/build/components/types/src/components/Tabs/Tabs.static.d.ts +12 -0
  27. package/build/lib/base.css +1 -1
  28. package/build/lib/base.css.map +1 -1
  29. package/build/lib/components.css +1 -1
  30. package/build/lib/components.css.map +1 -1
  31. package/build/lib/footer.css +1 -1
  32. package/build/lib/footer.css.map +1 -1
  33. package/build/lib/megamenu.css +1 -1
  34. package/build/lib/megamenu.css.map +1 -1
  35. package/build/lib/scripts.js +1 -1
  36. package/build/lib/scripts.js.map +1 -1
  37. package/build/lib/style.css +1 -1
  38. package/build/lib/style.css.map +1 -1
  39. package/build/lib/utilities.css +1 -1
  40. package/build/lib/utilities.css.map +1 -1
  41. package/build/search-index.json +5 -5
  42. package/package.json +18 -18
  43. package/src/components/Breadcrumbs/styles/mixins.scss +14 -3
  44. package/src/components/Carousel/styles/mixins.scss +22 -2
  45. package/src/components/CarouselHero/CarouselHero.tsx +20 -6
  46. package/src/components/CarouselHero/tests/CarouselHero.conformance.test.jsx +2 -0
  47. package/src/components/CarouselHero/tests/CarouselHero.unit.test.jsx +78 -9
  48. package/src/components/Footer/styles/mixins.scss +2 -1
  49. package/src/components/Forms/Checkbox/styles/style.scss +13 -6
  50. package/src/components/Forms/InputStepper/InputStepper.tsx +2 -0
  51. package/src/components/Forms/InputStepper/styles/style.scss +25 -8
  52. package/src/components/Forms/InputStepper/tests/InputStepper.unit.test.jsx +8 -0
  53. package/src/components/Link/styles/mixins.scss +0 -1
  54. package/src/components/Megamenu/Megamenu.tsx +2 -2
  55. package/src/components/Megamenu/MegamenuBlog.tsx +2 -2
  56. package/src/components/Megamenu/styles/mixins.scss +20 -12
  57. package/src/components/Preview/CodeExample.tsx +66 -25
  58. package/src/components/Preview/Preview.tsx +26 -13
  59. package/src/components/Preview/PreviewGenerator.tsx +57 -32
  60. package/src/components/Preview/getElementDisplayName.ts +25 -0
  61. package/src/components/Stepbar/styles/config.scss +34 -17
  62. package/src/components/Stepbar/styles/mixins.scss +5 -3
  63. package/src/components/Tabs/Tabs.static.ts +157 -30
  64. package/src/components/Tabs/Tabs.tsx +62 -67
  65. package/src/components/Tabs/styles/config.scss +18 -25
  66. package/src/components/Tabs/styles/mixins.scss +93 -28
  67. package/src/components/Tabs/styles/style.scss +4 -15
  68. package/src/components/Tabs/tests/Tabs.unit.test.jsx +111 -0
  69. package/src/styles/base/globals.scss +2 -0
  70. package/src/styles/shame.scss +16 -3
  71. package/src/styles/tools/convert.scss +8 -0
  72. package/src/styles/utilities/horizontal-scroll.scss +7 -2
  73. package/src/styles/utilities/text.scss +0 -1
@@ -188,13 +188,32 @@
188
188
 
189
189
  @mixin scrollbar-base {
190
190
  position: relative;
191
+ overflow: visible;
191
192
  }
192
193
 
193
194
  @mixin scrollbar-horizontal {
194
- height: convert.to-rem(6px);
195
+ height: convert.to-rem(8px);
195
196
  appearance: none;
196
- background-color: var(--color-surface-moderate);
197
+ background-color: transparent;
197
198
  border-radius: 99px;
199
+
200
+ &::before {
201
+ content: "";
202
+ position: absolute;
203
+ top: convert.to-rem(1px);
204
+ right: 0;
205
+ bottom: convert.to-rem(1px);
206
+ left: 0;
207
+ background-color: var(--color-surface-moderate);
208
+ border-radius: 99px;
209
+ pointer-events: none;
210
+ }
211
+
212
+ &:hover .carousel__scrollbar-drag,
213
+ .carousel__scrollbar-drag:hover {
214
+ height: convert.to-rem(8px);
215
+ margin-top: 0;
216
+ }
198
217
  }
199
218
 
200
219
  @mixin scrollbar-drag {
@@ -202,6 +221,7 @@
202
221
  background-color: var(--color-fill-contrast);
203
222
  border-radius: 99px;
204
223
  height: convert.to-rem(6px);
224
+ margin-top: convert.to-rem(1px);
205
225
 
206
226
  &:hover {
207
227
  background-color: var(--color-fill-secondary) !important;
@@ -32,6 +32,7 @@ interface CarouselHeroProps {
32
32
  children?: ReactNode;
33
33
  tabs?: TabItem[];
34
34
  interval?: number;
35
+ enableAutoplay?: boolean;
35
36
  [key: string]: any;
36
37
  }
37
38
 
@@ -41,6 +42,7 @@ const CarouselHero: React.FC<CarouselHeroProps> = ({
41
42
  children,
42
43
  tabs = [],
43
44
  interval,
45
+ enableAutoplay = false,
44
46
  ...other
45
47
  }) => {
46
48
  const [carouselRef] = useStatic(CarouselHeroStatic);
@@ -56,11 +58,21 @@ const CarouselHero: React.FC<CarouselHeroProps> = ({
56
58
  pagination: CLASS_PAGINATION,
57
59
  };
58
60
 
61
+ const forwardedSwiperOptions = (() => {
62
+ if (!swiperOptions) return undefined;
63
+ if (enableAutoplay || !("autoplay" in swiperOptions)) return swiperOptions;
64
+
65
+ const { autoplay: _autoplay, ...rest } = swiperOptions;
66
+
67
+ return Object.keys(rest).length > 0 ? rest : undefined;
68
+ })();
69
+
59
70
  const hasAutoplay =
60
- (swiperOptions?.autoplay &&
71
+ enableAutoplay &&
72
+ (((swiperOptions?.autoplay &&
61
73
  typeof swiperOptions.autoplay === "object" &&
62
- (swiperOptions.autoplay as any).delay >= 1000) ||
63
- (interval && interval >= 1000);
74
+ (swiperOptions.autoplay as any).delay >= 1000) as boolean) ||
75
+ !!(interval && interval >= 1000));
64
76
 
65
77
  const playPauseIcon = "pause";
66
78
 
@@ -69,9 +81,11 @@ const CarouselHero: React.FC<CarouselHeroProps> = ({
69
81
  className={classes}
70
82
  ref={carouselRef}
71
83
  data-carousel-hero
72
- {...(interval && interval >= 1000 ? { "data-interval": interval } : {})}
73
- {...(swiperOptions
74
- ? { "data-swiper-options": JSON.stringify(swiperOptions) }
84
+ {...(enableAutoplay && interval && interval >= 1000
85
+ ? { "data-interval": interval }
86
+ : {})}
87
+ {...(forwardedSwiperOptions
88
+ ? { "data-swiper-options": JSON.stringify(forwardedSwiperOptions) }
75
89
  : {})}
76
90
  {...other}
77
91
  >
@@ -41,6 +41,7 @@ const exampleWithTabs = (
41
41
 
42
42
  const exampleWithAutoplay = (
43
43
  <CarouselHero
44
+ enableAutoplay
44
45
  interval={3000}
45
46
  tabs={[{ label: "Auto Tab 1" }, { label: "Auto Tab 2" }]}
46
47
  >
@@ -57,6 +58,7 @@ const exampleWithAutoplay = (
57
58
 
58
59
  const exampleWithComplexContent = (
59
60
  <CarouselHero
61
+ enableAutoplay
60
62
  tabs={[{ label: "Product 1" }, { label: "Product 2" }]}
61
63
  interval={5000}
62
64
  swiperOptions={{ speed: 300 }}
@@ -79,7 +79,9 @@ describe("rendering CarouselHero", () => {
79
79
  });
80
80
 
81
81
  it("play/pause button has proper ARIA label when displayed", () => {
82
- const { container } = render(<CarouselHero interval={3000} />);
82
+ const { container } = render(
83
+ <CarouselHero enableAutoplay interval={3000} />,
84
+ );
83
85
 
84
86
  const playPauseButton = container.querySelector(
85
87
  ".carousel-hero__play-pause",
@@ -171,9 +173,11 @@ describe("rendering CarouselHero", () => {
171
173
  expect(tabButtons[2]).toHaveAttribute("tabIndex", "-1");
172
174
  });
173
175
 
174
- it("shows play/pause button when interval is provided", () => {
176
+ it("shows play/pause button when autoplay is enabled and interval is provided", () => {
175
177
  const { container } = render(
176
- <CarouselHero interval={3000}>{children}</CarouselHero>,
178
+ <CarouselHero enableAutoplay interval={3000}>
179
+ {children}
180
+ </CarouselHero>,
177
181
  );
178
182
 
179
183
  expect(
@@ -181,6 +185,16 @@ describe("rendering CarouselHero", () => {
181
185
  ).toBe(1);
182
186
  });
183
187
 
188
+ it("does not show play/pause button when autoplay is not enabled", () => {
189
+ const { container } = render(
190
+ <CarouselHero interval={3000}>{children}</CarouselHero>,
191
+ );
192
+
193
+ expect(
194
+ container.getElementsByClassName("carousel-hero__play-pause").length,
195
+ ).toBe(0);
196
+ });
197
+
184
198
  it("does not show play/pause button when interval is not provided", () => {
185
199
  const { container } = render(<CarouselHero>{children}</CarouselHero>);
186
200
 
@@ -199,15 +213,26 @@ describe("rendering CarouselHero", () => {
199
213
  ).toBe(0);
200
214
  });
201
215
 
202
- it("sets data-interval attribute when interval is provided", () => {
216
+ it("sets data-interval attribute when autoplay is enabled and interval is provided", () => {
203
217
  const { container } = render(
204
- <CarouselHero interval={5000}>{children}</CarouselHero>,
218
+ <CarouselHero enableAutoplay interval={5000}>
219
+ {children}
220
+ </CarouselHero>,
205
221
  );
206
222
 
207
223
  const carousel = container.querySelector(".carousel-hero");
208
224
  expect(carousel).toHaveAttribute("data-interval", "5000");
209
225
  });
210
226
 
227
+ it("does not set data-interval attribute when autoplay is not enabled", () => {
228
+ const { container } = render(
229
+ <CarouselHero interval={5000}>{children}</CarouselHero>,
230
+ );
231
+
232
+ const carousel = container.querySelector(".carousel-hero");
233
+ expect(carousel).not.toHaveAttribute("data-interval");
234
+ });
235
+
211
236
  it("does not set data-interval attribute when interval is not provided", () => {
212
237
  const { container } = render(<CarouselHero>{children}</CarouselHero>);
213
238
 
@@ -243,7 +268,7 @@ describe("rendering CarouselHero", () => {
243
268
  expect(carousel.hasAttribute("data-swiper-options")).toBe(false);
244
269
  });
245
270
 
246
- it("shows play/pause button when swiperOptions has autoplay with delay >= 1000ms", () => {
271
+ it("shows play/pause button when autoplay is enabled and swiperOptions has autoplay with delay >= 1000ms", () => {
247
272
  const swiperOptions = {
248
273
  autoplay: {
249
274
  delay: 3000,
@@ -251,7 +276,9 @@ describe("rendering CarouselHero", () => {
251
276
  },
252
277
  };
253
278
  const { container } = render(
254
- <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
279
+ <CarouselHero enableAutoplay swiperOptions={swiperOptions}>
280
+ {children}
281
+ </CarouselHero>,
255
282
  );
256
283
 
257
284
  expect(
@@ -259,6 +286,28 @@ describe("rendering CarouselHero", () => {
259
286
  ).toBe(1);
260
287
  });
261
288
 
289
+ it("does not show play/pause button when autoplay is not enabled, even if swiperOptions includes autoplay", () => {
290
+ const swiperOptions = {
291
+ autoplay: {
292
+ delay: 3000,
293
+ disableOnInteraction: false,
294
+ },
295
+ };
296
+ const { container } = render(
297
+ <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
298
+ );
299
+
300
+ expect(
301
+ container.getElementsByClassName("carousel-hero__play-pause").length,
302
+ ).toBe(0);
303
+
304
+ const carousel = container.querySelector(".carousel-hero");
305
+ expect(carousel).not.toHaveAttribute(
306
+ "data-swiper-options",
307
+ JSON.stringify(swiperOptions),
308
+ );
309
+ });
310
+
262
311
  it("does not show play/pause button when swiperOptions autoplay delay < 1000ms", () => {
263
312
  const swiperOptions = {
264
313
  autoplay: {
@@ -266,7 +315,9 @@ describe("rendering CarouselHero", () => {
266
315
  },
267
316
  };
268
317
  const { container } = render(
269
- <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
318
+ <CarouselHero enableAutoplay swiperOptions={swiperOptions}>
319
+ {children}
320
+ </CarouselHero>,
270
321
  );
271
322
 
272
323
  expect(
@@ -279,13 +330,31 @@ describe("rendering CarouselHero", () => {
279
330
  autoplay: true,
280
331
  };
281
332
  const { container } = render(
282
- <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
333
+ <CarouselHero enableAutoplay swiperOptions={swiperOptions}>
334
+ {children}
335
+ </CarouselHero>,
283
336
  );
284
337
 
285
338
  expect(
286
339
  container.getElementsByClassName("carousel-hero__play-pause").length,
287
340
  ).toBe(0);
288
341
  });
342
+ it("removes autoplay from forwarded swiperOptions until autoplay is enabled", () => {
343
+ const swiperOptions = {
344
+ autoplay: {
345
+ delay: 3000,
346
+ },
347
+ speed: 500,
348
+ };
349
+ const { container } = render(
350
+ <CarouselHero swiperOptions={swiperOptions}>{children}</CarouselHero>,
351
+ );
352
+
353
+ const carousel = container.querySelector(".carousel-hero");
354
+ expect(carousel.getAttribute("data-swiper-options")).toBe(
355
+ JSON.stringify({ speed: 500 }),
356
+ );
357
+ });
289
358
  });
290
359
 
291
360
  describe("Swiper integration", () => {
@@ -25,7 +25,8 @@
25
25
  &:focus,
26
26
  &:active {
27
27
  text-decoration: underline;
28
- text-underline-offset: convert.to-rem(4px);
28
+ text-underline-offset: convert.to-rem(2px);
29
+ text-decoration-thickness: auto;
29
30
  }
30
31
 
31
32
  &:focus-visible {
@@ -37,11 +37,17 @@
37
37
 
38
38
  .checkbox--toggle .checkbox + .checkbox-display {
39
39
  position: relative;
40
- background: color.$black;
41
- border-color: color.$black;
40
+ background: var(--color-fill-contrast);
41
+ border-color: var(--color-fill-contrast);
42
42
  background-image:
43
- url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M3 7L1 9l5 5L16 4l-2-2-8 8-3-3z' fill='%23000'/%3E%3C/svg%3E"),
43
+ url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M3 7L1 9l5 5L16 4l-2-2-8 8-3-3z' fill='%23fff'/%3E%3C/svg%3E"),
44
44
  url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath d='M12 2L10 0L6 4L2 0L0 2L4 6L0 10L2 12L6 8L10 12L12 10L8 6L12 2Z' fill='%23fff'/%3E%3C/svg%3E");
45
+
46
+ .is-dark & {
47
+ background-image:
48
+ url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cpath d='M3 7L1 9l5 5L16 4l-2-2-8 8-3-3z' fill='%23fff'/%3E%3C/svg%3E"),
49
+ url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath d='M12 2L10 0L6 4L2 0L0 2L4 6L0 10L2 12L6 8L10 12L12 10L8 6L12 2Z' fill='%23000'/%3E%3C/svg%3E");
50
+ }
45
51
  background-position:
46
52
  5px center,
47
53
  right 7px center;
@@ -51,19 +57,20 @@
51
57
  content: "";
52
58
  pointer-events: none;
53
59
  position: absolute;
54
- background: color.$white;
60
+ background: var(--color-fill-primary);
55
61
  top: 0;
56
62
  left: 0;
57
63
  width: 50%;
58
64
  height: 100%;
59
65
  transform: translateX(0);
60
66
  transition: transform 200ms ease-out;
67
+ border-radius: convert.to-rem(3px);
61
68
  }
62
69
  }
63
70
 
64
71
  .checkbox--toggle .checkbox:checked + .checkbox-display {
65
- background-color: var(--color-surface-secondary);
66
- border-color: var(--color-surface-secondary);
72
+ background-color: var(--color-surface-tertiary);
73
+ border-color: var(--color-surface-tertiary);
67
74
 
68
75
  &::after {
69
76
  transform: translateX(100%);
@@ -52,6 +52,7 @@ const InputStepper: React.FC<InputStepperProps> = ({
52
52
  <div
53
53
  className={cx(CLASS_ROOT, className, {
54
54
  [`${CLASS_ROOT}--disabled`]: isDisabled,
55
+ [`${CLASS_ROOT}--invalid`]: isInvalid,
55
56
  })}
56
57
  ref={elementRef}
57
58
  data-inputstepper={config ? JSON.stringify(config) : true}
@@ -70,6 +71,7 @@ const InputStepper: React.FC<InputStepperProps> = ({
70
71
  id={id}
71
72
  name={name}
72
73
  disabled={isDisabled}
74
+ isInvalid={isInvalid}
73
75
  htmlType="number"
74
76
  inputMode="numeric"
75
77
  />
@@ -14,8 +14,7 @@
14
14
  appearance: textfield;
15
15
  z-index: 0;
16
16
  border-radius: 0;
17
- padding: space.get("xsmall") space.get("xsmall") convert.to-rem(8px)
18
- space.get("xsmall");
17
+ padding: space.get("xsmall");
19
18
  text-align: center;
20
19
  border-left: 0;
21
20
  border-right: 0;
@@ -109,6 +108,22 @@
109
108
  z-index: 1;
110
109
  }
111
110
 
111
+ &--invalid {
112
+ .input-stepper__button,
113
+ .input-stepper__number,
114
+ .input-stepper__button--minus:active:not(:disabled),
115
+ .input-stepper__button--plus:active:not(:disabled) {
116
+ border-color: var(--color-border-negative);
117
+ }
118
+
119
+ @media (hover: hover) and (pointer: fine) {
120
+ .input-stepper__button--minus:hover:not(:disabled),
121
+ .input-stepper__button--plus:hover:not(:disabled) {
122
+ border-color: var(--color-border-negative);
123
+ }
124
+ }
125
+ }
126
+
112
127
  &__button--minus:disabled,
113
128
  &__button--plus:disabled {
114
129
  &::before {
@@ -116,13 +131,15 @@
116
131
  }
117
132
  }
118
133
 
119
- &__button--minus:hover:not(:disabled),
120
- &__button--plus:hover:not(:disabled) {
121
- background-color: var(--color-fill-contrast);
122
- border-color: var(--color-fill-contrast);
134
+ @media (hover: hover) and (pointer: fine) {
135
+ &__button--minus:hover:not(:disabled),
136
+ &__button--plus:hover:not(:disabled) {
137
+ background-color: var(--color-fill-contrast);
138
+ border-color: var(--color-fill-contrast);
123
139
 
124
- &::before {
125
- background-color: var(--color-fill-primary);
140
+ &::before {
141
+ background-color: var(--color-fill-primary);
142
+ }
126
143
  }
127
144
  }
128
145
 
@@ -28,6 +28,14 @@ describe("rendering InputStepper", () => {
28
28
  expect(getByLabelText("zvýšiť počet")).toBeDisabled();
29
29
  expect(getByRole("spinbutton")).toBeDisabled();
30
30
  });
31
+ it("has invalid classes when isInvalid prop is passed", () => {
32
+ const { getByTestId, getByRole } = render(
33
+ <InputStepper data-testid="test-id" id="id" isInvalid />,
34
+ );
35
+
36
+ expect(getByTestId("test-id")).toHaveClass("input-stepper--invalid");
37
+ expect(getByRole("spinbutton")).toHaveClass("is-invalid");
38
+ });
31
39
  it("has InputStepper removed input field, replaced it with text number and set defaultValue with when config prop is passed", () => {
32
40
  const { getByText } = render(
33
41
  <InputStepper
@@ -4,7 +4,6 @@
4
4
  @mixin base {
5
5
  font-weight: bold;
6
6
  text-decoration: underline;
7
- text-underline-offset: 0.1em;
8
7
  color: inherit;
9
8
  background: none;
10
9
  cursor: pointer;
@@ -414,9 +414,9 @@ export const Megamenu = ({
414
414
  aria-labelledby={ids.mobileMainTitleId}
415
415
  aria-hidden="true"
416
416
  >
417
- <h2 id={ids.mobileMainTitleId} className="sr-only">
417
+ <span id={ids.mobileMainTitleId} className="sr-only">
418
418
  Hlavné menu
419
- </h2>
419
+ </span>
420
420
  <button
421
421
  aria-label="Zatvoriť menu"
422
422
  className={CLASS_MOBILE_OVERLAY}
@@ -325,9 +325,9 @@ export const MegamenuBlog = ({
325
325
  aria-labelledby={ids.mobileMainTitleId}
326
326
  aria-hidden="true"
327
327
  >
328
- <h2 id={ids.mobileMainTitleId} className="sr-only">
328
+ <span id={ids.mobileMainTitleId} className="sr-only">
329
329
  Hlavné menu
330
- </h2>
330
+ </span>
331
331
  <button
332
332
  aria-label="Zatvoriť menu"
333
333
  className={CLASS_MOBILE_OVERLAY}
@@ -59,7 +59,7 @@
59
59
  font-size: inherit;
60
60
  text-decoration: underline;
61
61
  text-underline-offset: convert.to-rem(2px);
62
- text-decoration-thickness: 1px;
62
+ text-decoration-thickness: auto;
63
63
 
64
64
  &:hover,
65
65
  &:focus,
@@ -630,7 +630,8 @@
630
630
  @mixin mobile-account-logout {
631
631
  display: inline-block;
632
632
  text-decoration: underline;
633
- text-underline-offset: convert.to-rem(4px);
633
+ text-underline-offset: convert.to-rem(2px);
634
+ text-decoration-thickness: auto;
634
635
  margin-bottom: convert.to-rem(20px);
635
636
  font-weight: 400 !important;
636
637
  }
@@ -665,8 +666,15 @@
665
666
  }
666
667
 
667
668
  @mixin mobile-account-link {
668
- text-decoration: underline;
669
- text-underline-offset: convert.to-rem(4px);
669
+ text-decoration: none !important;
670
+
671
+ &:hover,
672
+ &:focus,
673
+ &:active {
674
+ text-decoration: underline !important;
675
+ text-underline-offset: convert.to-rem(2px);
676
+ text-decoration-thickness: auto;
677
+ }
670
678
  }
671
679
 
672
680
  @mixin container {
@@ -696,7 +704,7 @@
696
704
  a:focus {
697
705
  text-decoration: underline;
698
706
  text-underline-offset: convert.to-rem(2px);
699
- text-decoration-thickness: 1px;
707
+ text-decoration-thickness: auto;
700
708
  }
701
709
 
702
710
  @include breakpoint.get("md", "down") {
@@ -709,19 +717,15 @@
709
717
  }
710
718
 
711
719
  @mixin text-large {
712
- font-size: convert.to-rem(18px) !important;
720
+ font-size: convert.to-rem(28px) !important;
721
+ line-height: convert.to-rem(32px);
713
722
  font-weight: 700;
714
- line-height: convert.to-rem(22px);
715
-
716
- @include breakpoint.get("md", "down") {
717
- font-size: convert.to-rem(24px) !important;
718
- line-height: convert.to-rem(28px);
719
- }
720
723
  }
721
724
 
722
725
  @mixin caption {
723
726
  @include generate.css-map(typographyConfig.$caption, "default");
724
727
  margin-top: 0;
728
+ margin-bottom: convert.to-rem(20px);
725
729
  }
726
730
 
727
731
  @mixin caption-large {
@@ -817,6 +821,10 @@
817
821
  @mixin accordion {
818
822
  @include accordion.base;
819
823
  margin-bottom: 0px !important;
824
+
825
+ a {
826
+ text-decoration: none !important;
827
+ }
820
828
  }
821
829
 
822
830
  @mixin accordion-item {
@@ -6,16 +6,78 @@ import unescape from "unescape-html";
6
6
  import { formatHTML } from "../../utils/formatCode";
7
7
  import { Button } from "../Button";
8
8
  import Code from "../Code/";
9
+ import { getElementDisplayName } from "./getElementDisplayName";
9
10
 
10
11
  interface CodeExampleProps {
11
12
  codeJSXOptions?: Record<string, any>;
12
13
  codeTypes?: string[];
13
14
  children?: ReactNode;
15
+ htmlThemeClass?: string;
14
16
  jsxCode?: string; // Pre-generated JSX string (from server-side PreviewAuto)
15
17
  htmlCode?: ReactNode; // Code for HTML rendering
16
18
  [key: string]: any;
17
19
  }
18
20
 
21
+ const addClassToOpeningTag = (tag: string, className: string): string => {
22
+ if (tag.includes(' class="')) {
23
+ return tag.replace(/ class="([^"]*)"/, (_, existingClassName) => {
24
+ const mergedClassName = [existingClassName, className]
25
+ .filter(Boolean)
26
+ .join(" ");
27
+ return ` class="${mergedClassName}"`;
28
+ });
29
+ }
30
+
31
+ return tag.replace(/^<([\w-]+)/, `<$1 class="${className}"`);
32
+ };
33
+
34
+ const applyThemeClassToMarkup = (
35
+ markup: string,
36
+ themeClass?: string,
37
+ wrapMultipleRoots = false,
38
+ ): string => {
39
+ if (!themeClass || !markup.trim()) {
40
+ return markup;
41
+ }
42
+
43
+ if (wrapMultipleRoots) {
44
+ return `<div class="${themeClass}">${markup}</div>`;
45
+ }
46
+
47
+ return markup.replace(/^<[^>]+>/, (openingTag) =>
48
+ addClassToOpeningTag(openingTag, themeClass),
49
+ );
50
+ };
51
+
52
+ const renderMarkupToHtml = (markup: ReactNode, themeClass?: string): string => {
53
+ if (!markup) {
54
+ return "";
55
+ }
56
+
57
+ if (typeof markup === "string") {
58
+ return markup;
59
+ }
60
+
61
+ if (Array.isArray(markup)) {
62
+ const renderedMarkup = markup
63
+ .map((markupItem) =>
64
+ renderToStaticMarkup(markupItem as React.ReactElement),
65
+ )
66
+ .join("");
67
+
68
+ return applyThemeClassToMarkup(
69
+ renderedMarkup,
70
+ themeClass,
71
+ markup.length > 1,
72
+ );
73
+ }
74
+
75
+ return applyThemeClassToMarkup(
76
+ renderToStaticMarkup(markup as React.ReactElement),
77
+ themeClass,
78
+ );
79
+ };
80
+
19
81
  /**
20
82
  * Remove props that are undefined or null
21
83
  * Don't show React.Fragment in code example
@@ -68,25 +130,7 @@ const getJSXAsStringFromMarkup = (
68
130
  showDefaultProps: false,
69
131
  showFunctions: true,
70
132
  functionValue: (fn: any) => fn.name,
71
- displayName: (ReactElement: any) => {
72
- // Try to get display name from various sources
73
- if (ReactElement.props && ReactElement.props.mdxType) {
74
- return ReactElement.props.mdxType;
75
- }
76
- if (ReactElement.type && ReactElement.type.displayName) {
77
- return ReactElement.type.displayName;
78
- }
79
- if (ReactElement.type && ReactElement.type.name) {
80
- return ReactElement.type.name;
81
- }
82
- if (typeof ReactElement.type === "string") {
83
- return ReactElement.type;
84
- }
85
- // Fallback to type name or 'Component'
86
- return (
87
- ReactElement.type?.displayName || ReactElement.type?.name || "Component"
88
- );
89
- },
133
+ displayName: getElementDisplayName,
90
134
  filterProps: ["mdxType", "originalType", ...filterProps],
91
135
  ...otherOptions,
92
136
  };
@@ -124,6 +168,7 @@ const CodeExample: React.FC<CodeExampleProps> = ({
124
168
  children,
125
169
  codeJSXOptions,
126
170
  codeTypes = ["html", "jsx"],
171
+ htmlThemeClass,
127
172
  jsxCode,
128
173
  htmlCode,
129
174
  ...other
@@ -184,18 +229,14 @@ const CodeExample: React.FC<CodeExampleProps> = ({
184
229
  typeof htmlCode === "string"
185
230
  ? unescape(htmlCode)
186
231
  : unescape(
187
- formatHTML(
188
- renderToStaticMarkup(htmlCode as React.ReactElement),
189
- ),
232
+ formatHTML(renderMarkupToHtml(htmlCode, htmlThemeClass)),
190
233
  );
191
234
  } else {
192
235
  codeToShow =
193
236
  typeof children === "string"
194
237
  ? unescape(children)
195
238
  : unescape(
196
- formatHTML(
197
- renderToStaticMarkup(children as React.ReactElement),
198
- ),
239
+ formatHTML(renderMarkupToHtml(children, htmlThemeClass)),
199
240
  );
200
241
  }
201
242
  break;