@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
@@ -8,10 +8,6 @@ import { Tab } from "./Tab";
8
8
  import type { TabPanelProps } from "./TabPanel";
9
9
  import TabsStatic from "./Tabs.static";
10
10
 
11
- export const variants = ["standard", "light"] as const;
12
-
13
- export type TabsVariant = (typeof variants)[number];
14
-
15
11
  interface TabsProps extends React.HTMLAttributes<HTMLUListElement> {
16
12
  /** Active Tab index */
17
13
  activeTabIndex?: number;
@@ -23,8 +19,6 @@ interface TabsProps extends React.HTMLAttributes<HTMLUListElement> {
23
19
  isFullWidth?: boolean;
24
20
  /** Tabs behave as links rather than tabs */
25
21
  isLink?: boolean;
26
- /** Visual variant of the tabs */
27
- variant?: TabsVariant;
28
22
  /** Tab panels as children */
29
23
  children: React.ReactElement<TabPanelProps>[];
30
24
  }
@@ -36,7 +30,6 @@ const Tabs: React.FC<TabsProps> = ({
36
30
  isFullWidth,
37
31
  isLink,
38
32
  hasEqualTabWidth,
39
- variant = "standard",
40
33
  children,
41
34
  ...other
42
35
  }) => {
@@ -46,80 +39,82 @@ const Tabs: React.FC<TabsProps> = ({
46
39
  CLASS_TABNAV,
47
40
  { [`${CLASS_TABNAV}--equal`]: hasEqualTabWidth },
48
41
  { [`${CLASS_TABNAV}--fullwidth`]: isFullWidth },
49
- { [`${CLASS_TABNAV}--light`]: variant === "light" },
50
42
  classesTabNav,
51
43
  className,
52
44
  );
53
45
 
54
46
  const [tabListRef] = useStatic(TabsStatic);
55
47
 
56
- function getTabs() {
57
- return children
58
- .filter((tabPanel) => tabPanel && React.isValidElement(tabPanel))
59
- .map((tabPanel, i) => {
60
- const isActive = i === activeTabIndex;
61
- const props = tabPanel.props || {};
62
- const {
63
- renderTab = undefined,
64
- id,
65
- isDisabled,
66
- tab,
67
- href,
68
- } = props as TabPanelProps;
69
-
70
- // Generate ID if not provided
71
- const tabId = id || `tab-${i}`;
72
-
73
- if (!renderTab) {
74
- return (
75
- <Tab
76
- key={tabId}
77
- controls={!href ? tabId : ""}
78
- href={href}
79
- isDisabled={isDisabled}
80
- isActive={isActive}
81
- >
82
- {tab}
83
- </Tab>
84
- );
85
- }
48
+ const tabPanels = React.Children.toArray(children).filter(
49
+ (tabPanel): tabPanel is React.ReactElement<TabPanelProps> =>
50
+ React.isValidElement(tabPanel),
51
+ );
86
52
 
87
- const renderedTab = renderTab(props as TabPanelProps);
88
- return React.cloneElement(renderedTab, {
89
- key: tabId,
90
- isActive,
91
- } as React.HTMLAttributes<HTMLElement>);
92
- });
53
+ function getTabs() {
54
+ return tabPanels.map((tabPanel, i) => {
55
+ const isActive = i === activeTabIndex;
56
+ const props = tabPanel.props || {};
57
+ const {
58
+ renderTab = undefined,
59
+ id,
60
+ isDisabled,
61
+ tab,
62
+ href,
63
+ } = props as TabPanelProps;
64
+
65
+ // Generate ID if not provided
66
+ const tabId = id || `tab-${i}`;
67
+
68
+ if (!renderTab) {
69
+ return (
70
+ <Tab
71
+ key={tabId}
72
+ controls={!href ? tabId : ""}
73
+ href={href}
74
+ isDisabled={isDisabled}
75
+ isActive={isActive}
76
+ >
77
+ {tab}
78
+ </Tab>
79
+ );
80
+ }
81
+
82
+ const renderedTab = renderTab(props as TabPanelProps);
83
+ return React.cloneElement(renderedTab, {
84
+ key: tabId,
85
+ isActive,
86
+ } as React.HTMLAttributes<HTMLElement>);
87
+ });
93
88
  }
94
89
 
95
90
  function getPanels() {
96
- return children
97
- .filter((tabPanel) => tabPanel && React.isValidElement(tabPanel))
98
- .map((tabPanel, i) => {
99
- const isActive = i === activeTabIndex;
100
- const props = tabPanel.props || {};
101
- const { id } = props;
102
- const tabId = id || `tab-${i}`;
103
- return React.cloneElement(tabPanel, {
104
- key: tabId,
105
- isActive,
106
- tab: undefined,
107
- } as Partial<TabPanelProps>);
108
- });
91
+ return tabPanels.map((tabPanel, i) => {
92
+ const isActive = i === activeTabIndex;
93
+ const props = tabPanel.props || {};
94
+ const { id } = props;
95
+ const tabId = id || `tab-${i}`;
96
+ return React.cloneElement(tabPanel, {
97
+ key: tabId,
98
+ isActive,
99
+ tab: undefined,
100
+ } as Partial<TabPanelProps>);
101
+ });
109
102
  }
110
103
 
111
104
  return (
112
105
  <>
113
- <ul
114
- className={tabNavClasses}
115
- role={isLink ? "navigation" : "tablist"}
116
- ref={tabListRef}
117
- data-tabs={isLink ? undefined : "true"}
118
- {...other}
119
- >
120
- {getTabs()}
121
- {isFullWidth && <li role="presentation" className="tab-list__hr" />}
122
- </ul>
106
+ <div className="tab-list__viewport">
107
+ <ul
108
+ className={tabNavClasses}
109
+ role={isLink ? "navigation" : "tablist"}
110
+ ref={tabListRef}
111
+ data-tabs={isLink ? undefined : "true"}
112
+ {...other}
113
+ >
114
+ {getTabs()}
115
+ {isFullWidth && <li role="presentation" className="tab-list__hr" />}
116
+ </ul>
117
+ </div>
123
118
  {!isLink ? getPanels() : null}
124
119
  </>
125
120
  );
@@ -1,8 +1,12 @@
1
+ @use "../../../styles/tokens/base";
1
2
  @use "../../../styles/tokens/space";
2
3
  @use "../../../styles/tools/convert";
3
4
 
4
5
  $outline-width: convert.to-rem(2px);
5
- $negative-outline-width: $outline-width * -1;
6
+ $focusring-space: convert.to-rem(
7
+ base.$focusring-width + base.$focusring-offset
8
+ );
9
+ $negative-outline-width: $focusring-space * -1;
6
10
 
7
11
  $tablist-spacing: (
8
12
  margin: $negative-outline-width $negative-outline-width
@@ -10,50 +14,39 @@ $tablist-spacing: (
10
14
  space.get() + $negative-outline-width,
11
15
  )
12
16
  $negative-outline-width,
13
- padding: $outline-width,
17
+ padding: $focusring-space,
14
18
  );
15
19
 
16
20
  $tab: (
17
21
  default: (
18
22
  color: var(--color-text-default),
19
- box-shadow: inset 0 -2px 0 0 var(--color-border-contrast),
23
+ background-color: transparent,
24
+ box-shadow: inset 0 -1px 0 0 var(--color-surface-moderate),
20
25
  ),
21
26
  active: (
22
- color: var(--color-text-accent),
27
+ color: var(--color-text-default),
28
+ background-color: var(--color-fill-moderate),
23
29
  box-shadow: (
24
- inset -2px 0 0 0 var(--color-border-contrast),
25
- inset 0 2px 0 0 var(--color-border-contrast),
26
- inset 2px 0 0 0 var(--color-border-contrast),
30
+ inset 0 4px 0 0 var(--color-border-accent),
31
+ inset 0 -1px 0 0 var(--color-fill-moderate),
27
32
  ),
28
33
  ),
29
34
  hover: (
30
35
  color: var(--color-text-accent),
36
+ background-color: transparent,
37
+ box-shadow: inset 0 -1px 0 0 var(--color-surface-moderate),
31
38
  ),
32
39
  disabled: (
33
- color: var(--color-surface-moderate),
34
- ),
35
- );
36
-
37
- $tab-light: (
38
- default: (
39
- box-shadow: none "!important",
40
- ),
41
- active: (
42
- box-shadow: inset 0 -4px 0 0 var(--color-border-accent) "!important",
43
- ),
44
- hover: (
45
- box-shadow: none "!important",
46
- ),
47
- disabled: (
48
- box-shadow: none "!important",
40
+ color: var(--color-text-disabled),
41
+ background-color: transparent,
49
42
  ),
50
43
  );
51
44
 
52
45
  $tab-sizes: (
53
46
  default: (
54
- padding: space.get("small") space.get(),
47
+ padding: convert.to-rem(15px) convert.to-rem(20px),
55
48
  ),
56
49
  large: (
57
- padding: space.get("small") space.get(),
50
+ padding: convert.to-rem(20px),
58
51
  ),
59
52
  );
@@ -1,10 +1,61 @@
1
1
  @use "./config";
2
2
  @use "../../../styles/tokens/base";
3
3
  @use "../../../styles/tokens/space";
4
+ @use "../../../styles/tools/convert";
4
5
  @use "../../../styles/tools/generate";
5
6
 
6
- @mixin list-base($spacing: config.$tablist-spacing) {
7
+ $tab-focus-radius: convert.to-rem(5px);
8
+ $tab-focusring-space: convert.to-rem(
9
+ base.$focusring-width + base.$focusring-offset
10
+ );
11
+ $tab-overflow-fade-width: convert.to-rem(72px);
12
+
13
+ @mixin list-viewport {
7
14
  position: relative;
15
+ overflow: hidden;
16
+ padding: $tab-focusring-space $tab-focusring-space 0;
17
+
18
+ &::before,
19
+ &::after {
20
+ z-index: 2;
21
+ width: $tab-overflow-fade-width;
22
+ content: "";
23
+ position: absolute;
24
+ top: 0;
25
+ height: 100%;
26
+ pointer-events: none;
27
+ opacity: 0;
28
+ transition: opacity 0.2s ease;
29
+ }
30
+
31
+ &::before {
32
+ left: 0;
33
+ background: linear-gradient(
34
+ to left,
35
+ transparent 0%,
36
+ var(--color-background-primary) 100%
37
+ );
38
+ }
39
+
40
+ &::after {
41
+ right: 0;
42
+ background: linear-gradient(
43
+ to right,
44
+ transparent 0%,
45
+ var(--color-background-primary) 100%
46
+ );
47
+ }
48
+
49
+ &.has-left-overflow::before {
50
+ opacity: 1;
51
+ }
52
+
53
+ &.has-right-overflow::after {
54
+ opacity: 1;
55
+ }
56
+ }
57
+
58
+ @mixin list-base($spacing: config.$tablist-spacing) {
8
59
  display: flex;
9
60
  overflow-x: auto;
10
61
  overflow-y: visible;
@@ -16,6 +67,10 @@
16
67
 
17
68
  @mixin list-equal {
18
69
  flex-grow: 1;
70
+
71
+ .tab-list__tab {
72
+ text-align: center;
73
+ }
19
74
  }
20
75
 
21
76
  @mixin list-item {
@@ -28,54 +83,68 @@
28
83
  flex: 1 1 auto;
29
84
  display: flex;
30
85
  flex-flow: column;
86
+ justify-content: center;
31
87
  height: initial;
32
88
  position: relative;
33
- font-weight: 600;
89
+ font-weight: 700;
34
90
  background: transparent;
35
91
  border-width: 0;
36
92
  text-align: left;
93
+ white-space: nowrap;
94
+ cursor: pointer;
95
+
96
+ &::after {
97
+ content: "";
98
+ position: absolute;
99
+ inset: $tab-focusring-space * -1;
100
+ border: base.$focus-outline;
101
+ border-radius: calc(#{$tab-focus-radius} + #{$tab-focusring-space});
102
+ opacity: 0;
103
+ pointer-events: none;
104
+ }
37
105
 
38
106
  &:focus {
39
107
  z-index: 1;
108
+ outline-width: 0;
109
+ outline-color: transparent;
40
110
  }
41
111
 
42
- @include base.focusring-flush;
43
- }
112
+ &:focus::after {
113
+ opacity: 1;
114
+ }
44
115
 
45
- @mixin color-variant($config: config.$tab) {
46
- @include generate.css-map($config, "default");
116
+ &:focus-visible {
117
+ outline-width: 0;
118
+ outline-color: transparent;
119
+ }
47
120
 
48
- &[aria-selected="true"] {
49
- @include generate.css-map($config, "active");
121
+ &:focus-visible::after {
122
+ opacity: 1;
50
123
  }
51
124
 
52
- &:hover {
53
- @include generate.css-map(config.$tab, "hover");
125
+ &:focus:not(:focus-visible)::after {
126
+ opacity: 0;
54
127
  }
55
128
 
56
- &[aria-disabled="true"] {
57
- @include generate.css-map(config.$tab, "disabled");
129
+ &[aria-selected="true"] {
130
+ z-index: 1;
58
131
  }
59
132
  }
60
133
 
61
- @mixin tab-light {
62
- @include generate.css-map(config.$tab-light, "default");
63
-
64
- &:hover {
65
- @include generate.css-map(config.$tab-light, "hover");
66
- }
134
+ @mixin color-variant($config: config.$tab) {
135
+ @include generate.css-map($config, "default");
67
136
 
68
137
  &[aria-selected="true"] {
69
- @include generate.css-map(config.$tab-light, "active");
138
+ @include generate.css-map($config, "active");
70
139
  }
71
140
 
72
- &[aria-disabled="true"] {
73
- @include generate.css-map(config.$tab-light, "disabled");
141
+ &:hover:not([aria-selected="true"]):not([aria-disabled="true"]) {
142
+ @include generate.css-map(config.$tab, "hover");
74
143
  }
75
- }
76
144
 
77
- @mixin tab-centered {
78
- align-items: center;
145
+ &[aria-disabled="true"]:not([aria-selected="true"]) {
146
+ @include generate.css-map(config.$tab, "disabled");
147
+ }
79
148
  }
80
149
 
81
150
  @mixin tab-size($size, $config: config.$tab-sizes) {
@@ -85,10 +154,6 @@
85
154
  @mixin underline {
86
155
  flex: 1 1 auto;
87
156
  max-width: none;
88
- box-shadow: inset 0 -2px 0 0 var(--color-border-contrast);
89
- }
90
-
91
- @mixin underline-light {
92
157
  box-shadow: inset 0 -1px 0 0 var(--color-surface-moderate);
93
158
  }
94
159
 
@@ -5,6 +5,10 @@
5
5
  @use "../../../styles/typography/mixins" as typography;
6
6
 
7
7
  @layer components {
8
+ .tab-list__viewport {
9
+ @include mixins.list-viewport;
10
+ }
11
+
8
12
  .tab-list {
9
13
  $this: &;
10
14
 
@@ -21,10 +25,6 @@
21
25
  #{$this}--equal & {
22
26
  @include mixins.list-equal-item;
23
27
  }
24
-
25
- #{$this}--light & {
26
- @include mixins.underline-light;
27
- }
28
28
  }
29
29
 
30
30
  &__tab {
@@ -36,21 +36,10 @@
36
36
  @include mixins.tab-size($size);
37
37
  }
38
38
  }
39
- #{$this}--light & {
40
- @include mixins.tab-light;
41
- }
42
-
43
- #{$this}--light#{$this}--equal & {
44
- @include mixins.tab-centered;
45
- }
46
39
  }
47
40
 
48
41
  &__hr {
49
42
  @include mixins.underline;
50
-
51
- #{$this}--light & {
52
- @include mixins.underline-light;
53
- }
54
43
  }
55
44
  }
56
45
  }
@@ -2,6 +2,7 @@ import { fireEvent, render, screen } from "@testing-library/react";
2
2
  import userEvent from "@testing-library/user-event";
3
3
  import { TabPanel } from "../TabPanel";
4
4
  import { Tabs } from "../Tabs";
5
+ import TabsStatic from "../Tabs.static";
5
6
 
6
7
  const arr = [1, 2, 3, 4];
7
8
 
@@ -98,6 +99,116 @@ describe("rendering Tabs", () => {
98
99
  }
99
100
  }
100
101
  });
102
+
103
+ it("toggles left and right overflow classes based on scroll position", () => {
104
+ const { getByTestId } = render(<TabsExample />);
105
+ const tabList = getByTestId("test-id");
106
+ const viewport = tabList.parentElement;
107
+ const tabsStatic = TabsStatic.getInstance(tabList);
108
+
109
+ let scrollLeft = 0;
110
+ Object.defineProperty(tabList, "clientWidth", {
111
+ configurable: true,
112
+ value: 200,
113
+ });
114
+ Object.defineProperty(tabList, "scrollWidth", {
115
+ configurable: true,
116
+ value: 500,
117
+ });
118
+ Object.defineProperty(tabList, "scrollLeft", {
119
+ configurable: true,
120
+ get: () => scrollLeft,
121
+ set: (value) => {
122
+ scrollLeft = value;
123
+ },
124
+ });
125
+
126
+ tabsStatic?.update();
127
+
128
+ expect(viewport).not.toHaveClass("has-left-overflow");
129
+ expect(viewport).toHaveClass("has-right-overflow");
130
+
131
+ scrollLeft = 300;
132
+ fireEvent.scroll(tabList);
133
+
134
+ expect(viewport).toHaveClass("has-left-overflow");
135
+ expect(viewport).not.toHaveClass("has-right-overflow");
136
+ });
137
+
138
+ it("centers clicked active tab inside the scroll container", () => {
139
+ const { getByTestId, container } = render(<TabsExample />);
140
+ const tabList = getByTestId("test-id");
141
+ const secondTab = container.querySelector(
142
+ 'button[aria-controls="tabpanel-2"]',
143
+ );
144
+ const scrollToSpy = vi.fn();
145
+
146
+ Object.defineProperty(tabList, "clientWidth", {
147
+ configurable: true,
148
+ value: 200,
149
+ });
150
+ Object.defineProperty(tabList, "scrollWidth", {
151
+ configurable: true,
152
+ value: 600,
153
+ });
154
+ Object.defineProperty(tabList, "scrollLeft", {
155
+ configurable: true,
156
+ value: 180,
157
+ writable: true,
158
+ });
159
+ Object.defineProperty(tabList, "getBoundingClientRect", {
160
+ configurable: true,
161
+ value: () => ({
162
+ top: 0,
163
+ bottom: 0,
164
+ left: 0,
165
+ right: 200,
166
+ width: 200,
167
+ height: 0,
168
+ x: 0,
169
+ y: 0,
170
+ toJSON: () => ({}),
171
+ }),
172
+ });
173
+ Object.defineProperty(secondTab, "getBoundingClientRect", {
174
+ configurable: true,
175
+ value: () => ({
176
+ top: 0,
177
+ bottom: 0,
178
+ left: 40,
179
+ right: 120,
180
+ width: 80,
181
+ height: 0,
182
+ x: 40,
183
+ y: 0,
184
+ toJSON: () => ({}),
185
+ }),
186
+ });
187
+ tabList.scrollTo = scrollToSpy;
188
+
189
+ fireEvent.click(secondTab);
190
+
191
+ expect(scrollToSpy).toHaveBeenCalledWith({
192
+ left: 160,
193
+ behavior: "smooth",
194
+ });
195
+ });
196
+
197
+ it("does not center on pointer-style focus before click activation", () => {
198
+ const { getByTestId, container } = render(<TabsExample />);
199
+ const tabList = getByTestId("test-id");
200
+ const secondTab = container.querySelector(
201
+ 'button[aria-controls="tabpanel-2"]',
202
+ );
203
+ const scrollToSpy = vi.fn();
204
+
205
+ secondTab.matches = vi.fn((selector) => selector !== ":focus-visible");
206
+ tabList.scrollTo = scrollToSpy;
207
+
208
+ fireEvent.focus(secondTab);
209
+
210
+ expect(scrollToSpy).not.toHaveBeenCalled();
211
+ });
101
212
  });
102
213
  describe("checking fireEvents", () => {
103
214
  it("click in disabled tab button doesnt cause change", () => {
@@ -106,6 +106,8 @@ button:not(:disabled) {
106
106
 
107
107
  a {
108
108
  text-decoration: none;
109
+ text-underline-offset: 2px;
110
+ text-decoration-thickness: auto;
109
111
  }
110
112
 
111
113
  // stylelint-disable-next-line no-descending-specificity
@@ -1,8 +1,8 @@
1
1
  @layer utilities {
2
2
  /**
3
- * Resets for megamenu and footer
4
- * This reset is required due to default list spacing in ods 1 and will be removed once megamenu and footer components are migrated to 1.
5
- **/
3
+ * Resets for megamenu and footer
4
+ * This reset is required due to default list spacing in ods 1 and will be removed once megamenu and footer components are migrated to 1.
5
+ **/
6
6
  .osk-footer-menu,
7
7
  .mm-header ul,
8
8
  .megamenu-header ul {
@@ -14,4 +14,17 @@
14
14
  margin-bottom: 0;
15
15
  }
16
16
  }
17
+
18
+ /**
19
+ * Fixes for header and megamenu when modal is open
20
+ * This is required to prevent the header and megamenu from shifting when a modal is open due to scrollbar disappearance.
21
+ * This is a temporary fix and will be removed once the header and megamenu components are migrated to ods2
22
+ **/
23
+ body.has-modal {
24
+ .mm-header.is-sticky,
25
+ .megamenu-header.is-sticky,
26
+ [data-megamenu].is-sticky:not(.megamenu) {
27
+ padding-right: var(--ods-modal-scrollbar-width, 0px);
28
+ }
29
+ }
17
30
  }
@@ -3,10 +3,18 @@
3
3
  @use "../tokens/base";
4
4
 
5
5
  @function to-em($size, $font-size: base.$font-size) {
6
+ @if $size == 0 {
7
+ @return 0;
8
+ }
9
+
6
10
  @return math.div($size, $font-size) * 1em;
7
11
  }
8
12
 
9
13
  @function to-rem($size, $base: base.$font-size) {
14
+ @if $size == 0 {
15
+ @return 0;
16
+ }
17
+
10
18
  @return math.div($size, $base) * 1rem;
11
19
  }
12
20
 
@@ -15,14 +15,16 @@
15
15
 
16
16
  @supports selector(::-webkit-scrollbar) {
17
17
  &::-webkit-scrollbar {
18
- height: convert.to-rem(6px);
18
+ height: convert.to-rem(8px);
19
19
  appearance: none;
20
- background-color: var(--color-surface-moderate);
20
+ background-color: transparent;
21
21
  border-radius: 99px;
22
22
  }
23
23
 
24
24
  &::-webkit-scrollbar-track {
25
+ border: convert.to-rem(1px) solid transparent;
25
26
  background-color: var(--color-surface-moderate);
27
+ background-clip: content-box;
26
28
  border-radius: 99px;
27
29
  }
28
30
 
@@ -30,12 +32,15 @@
30
32
  opacity: 1;
31
33
  background-color: var(--color-fill-contrast);
32
34
  border-radius: 99px;
35
+ border: convert.to-rem(1px) solid transparent;
36
+ background-clip: content-box;
33
37
  }
34
38
 
35
39
  &:hover::-webkit-scrollbar-thumb,
36
40
  &:active::-webkit-scrollbar-thumb,
37
41
  &::-webkit-scrollbar-thumb:hover,
38
42
  &::-webkit-scrollbar-thumb:active {
43
+ border-width: 0;
39
44
  background-color: var(--color-fill-secondary) !important;
40
45
  }
41
46
  }
@@ -29,7 +29,6 @@
29
29
 
30
30
  .underline {
31
31
  text-decoration: underline !important;
32
- text-underline-offset: 0.1em !important;
33
32
  }
34
33
 
35
34
  .no-underline {