@orangesk/orange-design-system 3.6.1 → 3.7.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 (43) 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/Grid/style.css.map +1 -1
  4. package/build/components/Megamenu/style.css +1 -1
  5. package/build/components/Megamenu/style.css.map +1 -1
  6. package/build/components/index.js +1 -1
  7. package/build/components/index.js.map +1 -1
  8. package/build/components/types/index.d.ts +35 -1
  9. package/build/lib/components.css +1 -1
  10. package/build/lib/components.css.map +1 -1
  11. package/build/lib/footer.js +1 -1
  12. package/build/lib/footer.js.map +1 -1
  13. package/build/lib/megamenu.css +1 -1
  14. package/build/lib/megamenu.css.map +1 -1
  15. package/build/lib/megamenu.js +1 -1
  16. package/build/lib/megamenu.js.map +1 -1
  17. package/build/lib/scripts.js +1 -1
  18. package/build/lib/scripts.js.map +1 -1
  19. package/build/lib/style.css +1 -1
  20. package/build/lib/style.css.map +1 -1
  21. package/package.json +22 -22
  22. package/src/components/BodyBanner/styles/mixins.scss +7 -5
  23. package/src/components/Countdown/Countdown.shared.ts +5 -3
  24. package/src/components/Countdown/Countdown.static.ts +1 -1
  25. package/src/components/Countdown/tests/Countdown.static.test.jsx +19 -0
  26. package/src/components/Countdown/tests/CountdownTag.static.test.jsx +29 -0
  27. package/src/components/Footer/data.ts +4 -0
  28. package/src/components/Forms/SelectionTile/PLAN.md +206 -0
  29. package/src/components/Forms/SelectionTile/SelectionTile.tsx +145 -0
  30. package/src/components/Forms/SelectionTile/index.ts +5 -0
  31. package/src/components/Forms/SelectionTile/styles/mixins.scss +83 -0
  32. package/src/components/Forms/SelectionTile/styles/style.scss +58 -0
  33. package/src/components/Forms/SelectionTile/tests/SelectionTile.conformance.test.jsx +32 -0
  34. package/src/components/Forms/SelectionTile/tests/SelectionTile.unit.test.jsx +146 -0
  35. package/src/components/Forms/index.ts +1 -0
  36. package/src/components/Megamenu/Megamenu.tsx +20 -16
  37. package/src/components/Megamenu/MegamenuBlog.tsx +10 -7
  38. package/src/components/Megamenu/MyOrangeMobilePanel.tsx +2 -3
  39. package/src/components/Megamenu/constants.ts +3 -1
  40. package/src/components/Megamenu/styles/mixins.scss +38 -4
  41. package/src/components/Megamenu/styles/style.scss +12 -4
  42. package/src/components/Megamenu/tests/Megamenu.unit.test.jsx +32 -0
  43. package/src/components/index.ts +2 -0
@@ -0,0 +1,83 @@
1
+ @use "../../../../styles/tools/generate";
2
+ @use "../../../../styles/typography/config" as typography;
3
+ @use "../../../../styles/tokens/space";
4
+ @use "../../../../styles/tools/convert";
5
+
6
+ @mixin selection-tile-base {
7
+ position: relative;
8
+ display: flex;
9
+ width: 100%;
10
+ gap: space.get("small");
11
+ padding: space.get("medium");
12
+ border: 2px solid var(--color-border-subtle);
13
+ border-radius: space.get("small");
14
+ background: var(--color-fill-primary);
15
+ color: var(--color-text-default);
16
+ }
17
+
18
+ @mixin selection-tile-control {
19
+ flex: 0 0 auto;
20
+ width: space.get("medium");
21
+ min-height: space.get("medium");
22
+ }
23
+
24
+ @mixin selection-tile-body {
25
+ position: relative;
26
+ min-width: 0;
27
+ flex: 1 1 auto;
28
+ pointer-events: none;
29
+ gap: convert.to-rem(5px);
30
+ display: flex;
31
+ flex-direction: column;
32
+
33
+ *:last-child {
34
+ margin-bottom: 0;
35
+ }
36
+ }
37
+
38
+ @mixin selection-tile-hover {
39
+ border-color: var(--color-border-contrast);
40
+ }
41
+ @mixin selection-tile-focus {
42
+ outline: 2px solid var(--color-border-contrast);
43
+ outline-offset: 2px;
44
+ }
45
+ @mixin selection-tile-selected {
46
+ border-color: var(--color-border-accent);
47
+ }
48
+ @mixin selection-tile-warning {
49
+ border-color: var(--color-border-warning);
50
+ }
51
+ @mixin selection-tile-error {
52
+ border-color: var(--color-border-negative);
53
+ }
54
+
55
+ @mixin selection-tile-disabled {
56
+ border-color: var(--color-border-strong);
57
+ background-color: var(--color-surface-subtle);
58
+ color: var(--color-text-secondary);
59
+
60
+ > div {
61
+ cursor: not-allowed;
62
+ }
63
+ }
64
+
65
+ @mixin selection-tile-disabled-control {
66
+ background-color: var(--color-fill-primary);
67
+ border-color: var(--color-border-strong);
68
+ }
69
+
70
+ @mixin selection-tile-interactive {
71
+ position: relative;
72
+ z-index: 2;
73
+ pointer-events: auto;
74
+ }
75
+
76
+ @mixin selection-tile-message {
77
+ margin-top: 0px;
78
+ }
79
+
80
+ @mixin selection-tile-expander-summary {
81
+ @include generate.css-map(typography.$caption, "default");
82
+ font-weight: 700;
83
+ }
@@ -0,0 +1,58 @@
1
+ @use "./mixins";
2
+
3
+ @layer components {
4
+ .selection-tile {
5
+ @include mixins.selection-tile-base;
6
+
7
+ &__control {
8
+ @include mixins.selection-tile-control;
9
+ }
10
+ &__body {
11
+ @include mixins.selection-tile-body;
12
+ }
13
+
14
+ &:has(input:hover) {
15
+ @include mixins.selection-tile-hover;
16
+ }
17
+ &:has(input:focus-visible) {
18
+ @include mixins.selection-tile-focus;
19
+ }
20
+ &:has(input:checked) {
21
+ @include mixins.selection-tile-selected;
22
+ }
23
+
24
+ &--warning {
25
+ @include mixins.selection-tile-warning;
26
+ }
27
+ &--error,
28
+ &--invalid {
29
+ @include mixins.selection-tile-error;
30
+ }
31
+
32
+ &:has(input:disabled) {
33
+ @include mixins.selection-tile-disabled;
34
+
35
+ input:disabled {
36
+ cursor: default;
37
+ }
38
+
39
+ input:disabled:not(:checked) + .checkbox-display,
40
+ input:disabled:not(:checked) + .radio-display {
41
+ @include mixins.selection-tile-disabled-control;
42
+ }
43
+ }
44
+
45
+ .expander,
46
+ .block-action__override {
47
+ @include mixins.selection-tile-interactive;
48
+ }
49
+ .message {
50
+ @include mixins.selection-tile-message;
51
+ }
52
+
53
+ .expander__summary,
54
+ .expander__summary--opened {
55
+ @include mixins.selection-tile-expander-summary;
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,32 @@
1
+ import { render } from "@testing-library/react";
2
+ import { axe } from "vitest-axe";
3
+
4
+ import { BlockActionOverride } from "../../../BlockAction";
5
+ import { Expander } from "../../../Expander";
6
+ import { SelectionTile } from "..";
7
+
8
+ it("is valid and accessible with radio, checkbox, and Expander content", async () => {
9
+ const { container } = render(
10
+ <fieldset>
11
+ <legend>Choose options</legend>
12
+ <SelectionTile
13
+ type="radio"
14
+ id="radio-a"
15
+ name="options"
16
+ label="Radio option"
17
+ >
18
+ <BlockActionOverride>
19
+ <Expander summary="Detail">Radio details</Expander>
20
+ </BlockActionOverride>
21
+ </SelectionTile>
22
+ <SelectionTile type="checkbox" id="check-a" label="Checkbox option">
23
+ Checkbox details
24
+ </SelectionTile>
25
+ </fieldset>,
26
+ );
27
+
28
+ expect(container).toHTMLValidate({
29
+ rules: { "element-permitted-content": "off" },
30
+ });
31
+ expect(await axe(container)).toHaveNoViolations();
32
+ });
@@ -0,0 +1,146 @@
1
+ import { fireEvent, render, screen } from "@testing-library/react";
2
+ import { BlockActionOverride } from "../../../BlockAction";
3
+ import { Expander } from "../../../Expander";
4
+ import { SelectionTile } from "..";
5
+
6
+ describe("SelectionTile", () => {
7
+ it("renders a radio with an associated label", () => {
8
+ render(
9
+ <SelectionTile type="radio" id="choice-a" name="choices" label="Choice A">
10
+ <p>Additional content</p>
11
+ </SelectionTile>,
12
+ );
13
+
14
+ expect(screen.getByRole("radio", { name: "Choice A" })).toBeInTheDocument();
15
+ expect(screen.getByText("Additional content")).toBeInTheDocument();
16
+ expect(screen.getByRole("radio")).toHaveClass("radiocheck--fill");
17
+ expect(
18
+ screen.getByText("Additional content").closest(".block-action"),
19
+ ).toHaveClass("block-action");
20
+ });
21
+
22
+ it("renders a checkbox and preserves native interaction", () => {
23
+ render(<SelectionTile type="checkbox" id="choice-b" label="Choice B" />);
24
+ const checkbox = screen.getByRole("checkbox", { name: "Choice B" });
25
+
26
+ expect(checkbox).not.toBeChecked();
27
+ fireEvent.click(checkbox);
28
+ expect(checkbox).toBeChecked();
29
+ });
30
+
31
+ it("renders a disabled native checkbox", () => {
32
+ render(
33
+ <SelectionTile
34
+ type="checkbox"
35
+ id="choice-disabled"
36
+ label="Unavailable choice"
37
+ isDisabled
38
+ />,
39
+ );
40
+
41
+ expect(screen.getByRole("checkbox")).toBeDisabled();
42
+ });
43
+
44
+ it("selects the option through its tile label", () => {
45
+ render(
46
+ <SelectionTile type="checkbox" id="choice-label" label="Choice label">
47
+ <p>Tile content</p>
48
+ </SelectionTile>,
49
+ );
50
+ const checkbox = screen.getByRole("checkbox", { name: "Choice label" });
51
+
52
+ fireEvent.click(screen.getByText("Choice label"));
53
+
54
+ expect(checkbox).toBeChecked();
55
+ });
56
+
57
+ it("renders optional predefined slots and arbitrary children", () => {
58
+ render(
59
+ <SelectionTile
60
+ type="checkbox"
61
+ id="choice-slots"
62
+ inputProps={{ "aria-label": "Slot choice" }}
63
+ price="€9.99"
64
+ message="Feedback"
65
+ >
66
+ <span>Custom content</span>
67
+ <span>More details</span>
68
+ </SelectionTile>,
69
+ );
70
+
71
+ expect(
72
+ screen.getByRole("checkbox", { name: "Slot choice" }),
73
+ ).toBeInTheDocument();
74
+ expect(screen.getByRole("checkbox")).toHaveAttribute(
75
+ "aria-describedby",
76
+ "choice-slots-message",
77
+ );
78
+ expect(screen.getByText("€9.99")).toHaveClass(
79
+ "caption",
80
+ "text-accent",
81
+ "bold",
82
+ );
83
+ expect(screen.getByText("Feedback")).toHaveClass("selection-tile__message");
84
+ expect(screen.getByText("Custom content")).toBeInTheDocument();
85
+ expect(screen.getByText("More details")).toBeInTheDocument();
86
+ });
87
+
88
+ it("marks error status invalid and warning status advisory", () => {
89
+ const { rerender } = render(
90
+ <SelectionTile
91
+ type="radio"
92
+ id="choice-c"
93
+ name="choices"
94
+ label="Choice C"
95
+ status="error"
96
+ />,
97
+ );
98
+ expect(screen.getByRole("radio")).toHaveAttribute("aria-invalid", "true");
99
+
100
+ rerender(
101
+ <SelectionTile
102
+ type="radio"
103
+ id="choice-c"
104
+ name="choices"
105
+ label="Choice C"
106
+ status="warning"
107
+ />,
108
+ );
109
+ expect(screen.getByRole("radio")).not.toHaveAttribute("aria-invalid");
110
+ });
111
+
112
+ it("forwards explicit description relationships to the native input", () => {
113
+ render(
114
+ <SelectionTile
115
+ type="checkbox"
116
+ id="choice-message"
117
+ label="Choice with feedback"
118
+ inputProps={{ "aria-describedby": "choice-message-feedback" }}
119
+ message={<p id="choice-message-feedback">Additional feedback</p>}
120
+ />,
121
+ );
122
+
123
+ expect(screen.getByRole("checkbox")).toHaveAttribute(
124
+ "aria-describedby",
125
+ "choice-message-feedback",
126
+ );
127
+ });
128
+
129
+ it("keeps an Expander in the override layer", () => {
130
+ render(
131
+ <SelectionTile type="checkbox" id="choice-d" label="Choice D">
132
+ <BlockActionOverride>
133
+ <Expander summary="Detail">Details</Expander>
134
+ </BlockActionOverride>
135
+ </SelectionTile>,
136
+ );
137
+
138
+ const checkbox = screen.getByRole("checkbox");
139
+ const summary = screen.getByText("Detail");
140
+
141
+ expect(summary.closest(".block-action__override")).toBeInTheDocument();
142
+ fireEvent.click(summary);
143
+
144
+ expect(checkbox).not.toBeChecked();
145
+ });
146
+ });
@@ -12,5 +12,6 @@ export { Message } from "./Message";
12
12
  export { Radio } from "./Radio";
13
13
  export { RangeSlider } from "./RangeSlider";
14
14
  export { Select } from "./Select";
15
+ export { SelectionTile } from "./SelectionTile";
15
16
  export { TextArea } from "./TextArea";
16
17
  export { TextInput } from "./TextInput";
@@ -12,7 +12,6 @@ import {
12
12
  CLASS_CARD,
13
13
  CLASS_CONTAINER,
14
14
  CLASS_GRID,
15
- CLASS_HIDE_LG_ONLY,
16
15
  CLASS_HIDE_LG_UP,
17
16
  CLASS_HIDE_MD_DOWN,
18
17
  CLASS_MAIN,
@@ -29,14 +28,15 @@ import {
29
28
  CLASS_NAV_ITEM,
30
29
  CLASS_NAV_ITEM_LEAD,
31
30
  CLASS_NAV_ITEM_MAIN,
31
+ CLASS_NAV_ITEM_PUSH,
32
32
  CLASS_NAV_LINK,
33
33
  CLASS_NAV_LINK_CTA,
34
34
  CLASS_NAV_LINK_LOCALE,
35
+ CLASS_NAV_LOCALE,
35
36
  CLASS_NAV_MOBILE_LOCALE,
36
37
  CLASS_NAV_SELECT,
37
38
  CLASS_NAV_SELECT_WRAPPER,
38
39
  CLASS_NAV_SPACE_SMALL,
39
- CLASS_NAV_SPACER,
40
40
  CLASS_NAV_VERTICAL,
41
41
  CLASS_OVERLAY,
42
42
  CLASS_ROOT,
@@ -53,6 +53,7 @@ import {
53
53
  CLASS_TILE_LABEL,
54
54
  CLASS_TILES,
55
55
  CLASS_TOP,
56
+ CLASS_TOP_CONTENT,
56
57
  } from "./constants";
57
58
  import type { MegamenuTile, MenuItem, MenuSection } from "./data";
58
59
  import { megamenuTiles, menuSections } from "./data";
@@ -251,10 +252,10 @@ export const Megamenu = ({
251
252
  className={cx(CLASS_TOP, CLASS_HIDE_MD_DOWN)}
252
253
  data-hide-when-sticky="true"
253
254
  >
254
- <div className={CLASS_CONTAINER}>
255
+ <div className={cx(CLASS_CONTAINER, CLASS_TOP_CONTENT)}>
255
256
  <ul
256
257
  className={cx(CLASS_NAV, CLASS_NAV_SPACE_SMALL)}
257
- aria-label="Top menu"
258
+ aria-label="Zákaznícke a kontaktné odkazy"
258
259
  >
259
260
  <li className={CLASS_NAV_ITEM}>
260
261
  <a
@@ -270,14 +271,12 @@ export const Megamenu = ({
270
271
  Podnikatelia a malé firmy
271
272
  </a>
272
273
  </li>
273
- <li className={CLASS_NAV_ITEM}>
274
+ <li className={cx(CLASS_NAV_ITEM, CLASS_NAV_ITEM_PUSH)}>
274
275
  <a href="/" className={CLASS_NAV_LINK}>
275
276
  Velké firmy
276
277
  </a>
277
278
  </li>
278
279
 
279
- <li className={CLASS_NAV_SPACER} aria-hidden="true"></li>
280
-
281
280
  <li className={cx(CLASS_NAV_ITEM, CLASS_NAV_ITEM_LEAD)}>
282
281
  <a href="/" className={CLASS_NAV_LINK}>
283
282
  <MegamenuIcon
@@ -290,6 +289,11 @@ export const Megamenu = ({
290
289
  Kontakt
291
290
  </a>
292
291
  </li>
292
+ </ul>
293
+ <ul
294
+ className={cx(CLASS_NAV, CLASS_NAV_SPACE_SMALL, CLASS_NAV_LOCALE)}
295
+ aria-label="Výber jazyka"
296
+ >
293
297
  <li className={CLASS_NAV_ITEM}>
294
298
  <a href="/" className={cx(CLASS_NAV_LINK, "is-active")}>
295
299
  SK
@@ -307,7 +311,13 @@ export const Megamenu = ({
307
311
  <div className={CLASS_MAIN}>
308
312
  <div className={CLASS_CONTAINER}>
309
313
  <ul className={CLASS_NAV} aria-label="Hlavné menu">
310
- <li className={cx(CLASS_NAV_ITEM, CLASS_NAV_ITEM_MAIN)}>
314
+ <li
315
+ className={cx(
316
+ CLASS_NAV_ITEM,
317
+ CLASS_NAV_ITEM_MAIN,
318
+ CLASS_NAV_ITEM_PUSH,
319
+ )}
320
+ >
311
321
  <MegamenuLogoLink
312
322
  compactLogoOnly={compactLogoOnly}
313
323
  title={title}
@@ -373,6 +383,7 @@ export const Megamenu = ({
373
383
  className={cx(
374
384
  CLASS_NAV_ITEM,
375
385
  CLASS_NAV_ITEM_MAIN,
386
+ CLASS_NAV_ITEM_PUSH,
376
387
  CLASS_HIDE_MD_DOWN,
377
388
  )}
378
389
  >
@@ -388,11 +399,6 @@ export const Megamenu = ({
388
399
  </a>
389
400
  </li>
390
401
 
391
- <li
392
- className={cx(CLASS_NAV_SPACER, CLASS_HIDE_LG_ONLY)}
393
- aria-hidden="true"
394
- ></li>
395
-
396
402
  <li className={cx(CLASS_NAV_ITEM, CLASS_HIDE_MD_DOWN)}>
397
403
  <button
398
404
  type="button"
@@ -515,7 +521,7 @@ export const Megamenu = ({
515
521
  <div className={CLASS_MOBILE_HEADER}>
516
522
  <div className={CLASS_CONTAINER}>
517
523
  <ul className={cx(CLASS_NAV, CLASS_NAV_SPACE_SMALL)}>
518
- <li className={CLASS_NAV_ITEM}>
524
+ <li className={cx(CLASS_NAV_ITEM, CLASS_NAV_ITEM_PUSH)}>
519
525
  <div
520
526
  className={cx(
521
527
  CLASS_NAV_BUTTON,
@@ -535,8 +541,6 @@ export const Megamenu = ({
535
541
  </div>
536
542
  </li>
537
543
 
538
- <li className={CLASS_NAV_SPACER} aria-hidden="true"></li>
539
-
540
544
  <li className={CLASS_NAV_ITEM}>
541
545
  <MegamenuCloseButton
542
546
  ariaLabel="Zatvoriť menu"
@@ -16,10 +16,10 @@ import {
16
16
  CLASS_NAV_ICON_NO_GAP_MD_DOWN,
17
17
  CLASS_NAV_ITEM,
18
18
  CLASS_NAV_ITEM_MAIN,
19
+ CLASS_NAV_ITEM_PUSH,
19
20
  CLASS_NAV_LINK,
20
21
  CLASS_NAV_LINK_NO_LINE,
21
22
  CLASS_NAV_SPACE_SMALL,
22
- CLASS_NAV_SPACER,
23
23
  CLASS_NAV_VERTICAL,
24
24
  CLASS_OVERLAY,
25
25
  CLASS_ROOT,
@@ -75,7 +75,13 @@ export const MegamenuBlog = ({
75
75
  <div className={CLASS_MAIN}>
76
76
  <div className={CLASS_CONTAINER}>
77
77
  <ul className={CLASS_NAV} aria-label="Hlavné menu">
78
- <li className={cx(CLASS_NAV_ITEM, CLASS_NAV_ITEM_MAIN)}>
78
+ <li
79
+ className={cx(
80
+ CLASS_NAV_ITEM,
81
+ CLASS_NAV_ITEM_MAIN,
82
+ CLASS_NAV_ITEM_PUSH,
83
+ )}
84
+ >
79
85
  <MegamenuLogoLink
80
86
  compactLogoOnly={compactLogoOnly}
81
87
  title={title}
@@ -88,6 +94,7 @@ export const MegamenuBlog = ({
88
94
  className={cx(
89
95
  CLASS_NAV_ITEM,
90
96
  CLASS_NAV_ITEM_MAIN,
97
+ CLASS_NAV_ITEM_PUSH,
91
98
  CLASS_HIDE_MD_DOWN,
92
99
  )}
93
100
  >
@@ -99,8 +106,6 @@ export const MegamenuBlog = ({
99
106
  </a>
100
107
  </li>
101
108
 
102
- <li className={CLASS_NAV_SPACER} aria-hidden="true"></li>
103
-
104
109
  <li className={cx(CLASS_NAV_ITEM, CLASS_HIDE_MD_DOWN)}>
105
110
  <button
106
111
  type="button"
@@ -309,7 +314,7 @@ export const MegamenuBlog = ({
309
314
  <div className={CLASS_MOBILE_HEADER}>
310
315
  <div className={CLASS_CONTAINER}>
311
316
  <ul className={cx(CLASS_NAV, CLASS_NAV_SPACE_SMALL)}>
312
- <li className={CLASS_NAV_ITEM}>
317
+ <li className={cx(CLASS_NAV_ITEM, CLASS_NAV_ITEM_PUSH)}>
313
318
  <MegamenuLogoLink
314
319
  compactLogoOnly={compactLogoOnly}
315
320
  title={title}
@@ -318,8 +323,6 @@ export const MegamenuBlog = ({
318
323
  </MegamenuLogoLink>
319
324
  </li>
320
325
 
321
- <li className={CLASS_NAV_SPACER} aria-hidden="true"></li>
322
-
323
326
  <li className={CLASS_NAV_ITEM}>
324
327
  <MegamenuCloseButton
325
328
  ariaLabel="Zatvoriť menu"
@@ -19,8 +19,8 @@ import {
19
19
  CLASS_MOBILE_HEADER,
20
20
  CLASS_NAV,
21
21
  CLASS_NAV_ITEM,
22
+ CLASS_NAV_ITEM_PUSH,
22
23
  CLASS_NAV_SPACE_SMALL,
23
- CLASS_NAV_SPACER,
24
24
  CLASS_SUBNAV,
25
25
  CLASS_SUBNAV_ITEM,
26
26
  } from "./constants";
@@ -51,8 +51,7 @@ export const MyOrangeMobilePanel = ({
51
51
  <div className={CLASS_MOBILE_HEADER}>
52
52
  <div className={CLASS_CONTAINER}>
53
53
  <ul className={cx(CLASS_NAV, CLASS_NAV_SPACE_SMALL)}>
54
- <li className={CLASS_NAV_SPACER} aria-hidden="true"></li>
55
- <li className={CLASS_NAV_ITEM}>
54
+ <li className={cx(CLASS_NAV_ITEM, CLASS_NAV_ITEM_PUSH)}>
56
55
  <MegamenuCloseButton
57
56
  ariaLabel="Zatvoriť panel Môj Orange"
58
57
  target="my-orange"
@@ -1,6 +1,7 @@
1
1
  export const CLASS_ROOT = "megamenu";
2
2
 
3
3
  export const CLASS_TOP = `${CLASS_ROOT}__top`;
4
+ export const CLASS_TOP_CONTENT = `${CLASS_ROOT}__top-content`;
4
5
  export const CLASS_MAIN = `${CLASS_ROOT}__main`;
5
6
  export const CLASS_SUBMAIN = `${CLASS_ROOT}__submain`;
6
7
  export const CLASS_CONTAINER = `${CLASS_ROOT}__container`;
@@ -14,9 +15,11 @@ export const CLASS_TILE_LABEL = `${CLASS_ROOT}__tile-label`;
14
15
  export const CLASS_NAV = `${CLASS_ROOT}__nav`;
15
16
  export const CLASS_NAV_VERTICAL = `${CLASS_ROOT}__nav--vertical`;
16
17
  export const CLASS_NAV_SPACE_SMALL = `${CLASS_ROOT}__nav--space-small`;
18
+ export const CLASS_NAV_LOCALE = `${CLASS_ROOT}__nav--locale`;
17
19
  export const CLASS_NAV_MOBILE_LOCALE = `${CLASS_ROOT}__nav--mobile-locale`;
18
20
  export const CLASS_NAV_ITEM = `${CLASS_ROOT}__nav-item`;
19
21
  export const CLASS_NAV_ITEM_LEAD = `${CLASS_ROOT}__nav-item--lead`;
22
+ export const CLASS_NAV_ITEM_PUSH = `${CLASS_ROOT}__nav-item--push`;
20
23
  export const CLASS_NAV_ITEM_MAIN = `${CLASS_ROOT}__nav-item--main`;
21
24
  export const CLASS_NAV_LINK = `${CLASS_ROOT}__nav-link`;
22
25
  export const CLASS_NAV_LINK_LOCALE = `${CLASS_ROOT}__nav-link--locale`;
@@ -24,7 +27,6 @@ export const CLASS_NAV_LINK_NO_LINE = `${CLASS_ROOT}__nav-link--no-line`;
24
27
  export const CLASS_NAV_LINK_CTA = `${CLASS_ROOT}__nav-link--cta`;
25
28
  export const CLASS_NAV_SELECT = `${CLASS_ROOT}__nav-select`;
26
29
  export const CLASS_NAV_CART_ICON = `${CLASS_ROOT}__nav-cart-icon`;
27
- export const CLASS_NAV_SPACER = `${CLASS_ROOT}__nav-spacer`;
28
30
  export const CLASS_NAV_ICON = `${CLASS_ROOT}__nav-icon`;
29
31
  export const CLASS_NAV_ICON_NO_GAP_MD_DOWN = `${CLASS_NAV_ICON}--no-gap-md-down`;
30
32
  export const CLASS_NAV_ICON_CTA = `${CLASS_NAV_ICON}--cta`;
@@ -233,6 +233,10 @@
233
233
  gap: convert.to-rem(15px);
234
234
  }
235
235
 
236
+ @mixin nav-locale {
237
+ flex: 0 0 auto;
238
+ }
239
+
236
240
  @mixin nav-mobile-locale {
237
241
  position: relative;
238
242
  padding: convert.to-rem(15px) 0 !important;
@@ -261,6 +265,16 @@
261
265
  margin-right: convert.to-rem(10px);
262
266
  }
263
267
 
268
+ @mixin nav-item-push {
269
+ margin-inline-end: auto;
270
+
271
+ &#{config.$class-root}__nav-item--main:first-child {
272
+ @include breakpoint.get("lg") {
273
+ margin-inline-end: 0;
274
+ }
275
+ }
276
+ }
277
+
264
278
  @mixin nav-dropdown {
265
279
  position: absolute;
266
280
  top: calc(100% + 1px);
@@ -607,10 +621,25 @@
607
621
  }
608
622
  }
609
623
 
610
- @mixin nav-spacer {
611
- display: flex;
612
- flex: 1 0 1px;
613
- visibility: hidden;
624
+ @mixin top-content {
625
+ flex-direction: row;
626
+ align-items: center;
627
+ gap: convert.to-rem(15px);
628
+
629
+ > #{config.$class-root}__nav {
630
+ height: 100%;
631
+ margin-bottom: 0;
632
+ }
633
+
634
+ > #{config.$class-root}__nav:first-child {
635
+ flex: 1 1 0;
636
+ min-width: 0;
637
+ }
638
+
639
+ > #{config.$class-root}__nav:last-child {
640
+ flex: 0 0 auto;
641
+ width: auto;
642
+ }
614
643
  }
615
644
 
616
645
  @mixin subnav {
@@ -755,6 +784,11 @@
755
784
  height: convert.to-rem(80px);
756
785
  border-bottom: 1px solid var(--color-border-subtle);
757
786
 
787
+ #{config.$class-root}__nav-item--push:only-child {
788
+ margin-inline-start: auto;
789
+ margin-inline-end: 0;
790
+ }
791
+
758
792
  @include breakpoint.get("md", "down") {
759
793
  height: convert.to-rem(60px);
760
794
  }
@@ -36,6 +36,10 @@
36
36
  &--lead {
37
37
  @include mixins.nav-item-lead;
38
38
  }
39
+
40
+ &--push {
41
+ @include mixins.nav-item-push;
42
+ }
39
43
  }
40
44
 
41
45
  &--vertical {
@@ -46,6 +50,10 @@
46
50
  @include mixins.nav-space-small;
47
51
  }
48
52
 
53
+ &--locale {
54
+ @include mixins.nav-locale;
55
+ }
56
+
49
57
  &--mobile-locale {
50
58
  @include mixins.nav-mobile-locale;
51
59
  }
@@ -109,10 +117,6 @@
109
117
  @include mixins.nav-icon-cta;
110
118
  }
111
119
  }
112
-
113
- &-spacer {
114
- @include mixins.nav-spacer;
115
- }
116
120
  }
117
121
 
118
122
  &__subnav {
@@ -222,6 +226,10 @@
222
226
 
223
227
  &__container {
224
228
  @include mixins.container;
229
+
230
+ &#{config.$class-root}__top-content {
231
+ @include mixins.top-content;
232
+ }
225
233
  }
226
234
 
227
235
  &__grid {