@khanacademy/wonder-blocks-switch 1.0.5 → 1.1.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.
package/dist/index.js CHANGED
@@ -3,10 +3,7 @@
3
3
  var React = require('react');
4
4
  var aphrodite = require('aphrodite');
5
5
  var wonderBlocksCore = require('@khanacademy/wonder-blocks-core');
6
- var Color = require('@khanacademy/wonder-blocks-color');
7
- var Spacing = require('@khanacademy/wonder-blocks-spacing');
8
-
9
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
6
+ var wonderBlocksTheming = require('@khanacademy/wonder-blocks-theming');
10
7
 
11
8
  function _interopNamespace(e) {
12
9
  if (e && e.__esModule) return e;
@@ -27,8 +24,6 @@ function _interopNamespace(e) {
27
24
  }
28
25
 
29
26
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
30
- var Color__default = /*#__PURE__*/_interopDefaultLegacy(Color);
31
- var Spacing__default = /*#__PURE__*/_interopDefaultLegacy(Spacing);
32
27
 
33
28
  function _extends() {
34
29
  _extends = Object.assign ? Object.assign.bind() : function (target) {
@@ -45,9 +40,105 @@ function _extends() {
45
40
  return _extends.apply(this, arguments);
46
41
  }
47
42
 
43
+ const theme$1 = {
44
+ color: {
45
+ bg: {
46
+ switch: {
47
+ off: wonderBlocksTheming.tokens.color.offBlack50,
48
+ disabledOff: wonderBlocksTheming.tokens.color.offBlack32,
49
+ activeOff: wonderBlocksTheming.tokens.color.offBlack64,
50
+ on: wonderBlocksTheming.tokens.color.blue,
51
+ disabledOn: wonderBlocksTheming.tokens.color.fadedBlue,
52
+ activeOn: wonderBlocksTheming.tokens.color.activeBlue
53
+ },
54
+ slider: {
55
+ on: wonderBlocksTheming.tokens.color.white,
56
+ off: wonderBlocksTheming.tokens.color.white
57
+ },
58
+ icon: {
59
+ on: wonderBlocksTheming.tokens.color.blue,
60
+ disabledOn: wonderBlocksTheming.tokens.color.fadedBlue,
61
+ off: wonderBlocksTheming.tokens.color.offBlack50,
62
+ disabledOff: wonderBlocksTheming.tokens.color.offBlack32
63
+ }
64
+ },
65
+ outline: {
66
+ default: wonderBlocksTheming.tokens.color.blue
67
+ }
68
+ },
69
+ border: {
70
+ radius: {
71
+ small: wonderBlocksTheming.tokens.spacing.small_12,
72
+ full: wonderBlocksTheming.tokens.border.radius.full
73
+ }
74
+ },
75
+ size: {
76
+ height: {
77
+ none: 0,
78
+ medium: 20,
79
+ large: wonderBlocksTheming.tokens.spacing.large_24
80
+ },
81
+ width: {
82
+ none: 0,
83
+ small: wonderBlocksTheming.tokens.spacing.xxxxSmall_2,
84
+ medium: 20,
85
+ large: 40
86
+ },
87
+ offset: {
88
+ default: 1
89
+ }
90
+ },
91
+ spacing: {
92
+ slider: {
93
+ position: wonderBlocksTheming.tokens.spacing.xxxxSmall_2
94
+ },
95
+ icon: {
96
+ position: wonderBlocksTheming.tokens.spacing.xxxSmall_4
97
+ },
98
+ transform: {
99
+ default: `translateX(${wonderBlocksTheming.tokens.spacing.medium_16}px)`,
100
+ transition: "transform 0.15s ease-in-out"
101
+ }
102
+ }
103
+ };
104
+
105
+ const theme = wonderBlocksTheming.mergeTheme(theme$1, {
106
+ color: {
107
+ bg: {
108
+ switch: {
109
+ off: wonderBlocksTheming.tokens.color.white50,
110
+ disabledOff: wonderBlocksTheming.tokens.color.white32,
111
+ activeOff: wonderBlocksTheming.tokens.color.white50,
112
+ disabledOn: wonderBlocksTheming.tokens.color.activeBlue
113
+ },
114
+ slider: {
115
+ off: wonderBlocksTheming.tokens.color.eggplant
116
+ },
117
+ icon: {
118
+ off: wonderBlocksTheming.tokens.color.white,
119
+ disabledOff: wonderBlocksTheming.tokens.color.white50,
120
+ disabledOn: wonderBlocksTheming.tokens.color.activeBlue
121
+ }
122
+ }
123
+ }
124
+ });
125
+
126
+ const themes = {
127
+ default: theme$1,
128
+ khanmigo: theme
129
+ };
130
+ const SwitchThemeContext = wonderBlocksTheming.createThemeContext(theme$1);
131
+ function ThemedSwitch(props) {
132
+ const currentTheme = React__namespace.useContext(wonderBlocksTheming.ThemeSwitcherContext);
133
+ const theme = themes[currentTheme] || theme$1;
134
+ return React__namespace.createElement(SwitchThemeContext.Provider, {
135
+ value: theme
136
+ }, props.children);
137
+ }
138
+
48
139
  const StyledSpan = wonderBlocksCore.addStyle("span");
49
140
  const StyledInput = wonderBlocksCore.addStyle("input");
50
- const Switch = React__namespace.forwardRef(function Switch(props, ref) {
141
+ const SwitchCore = React__namespace.forwardRef(function SwitchCore(props, ref) {
51
142
  const {
52
143
  "aria-label": ariaLabel,
53
144
  "aria-labelledby": ariaLabelledBy,
@@ -59,64 +150,67 @@ const Switch = React__namespace.forwardRef(function Switch(props, ref) {
59
150
  onChange,
60
151
  testId
61
152
  } = props;
153
+ const ids = wonderBlocksCore.useUniqueIdWithMock("labeled-field");
154
+ const uniqueId = id != null ? id : ids.get("labeled-field-id");
155
+ const {
156
+ theme,
157
+ themeName
158
+ } = wonderBlocksTheming.useScopedTheme(SwitchThemeContext);
159
+ const sharedStyles = wonderBlocksTheming.useStyles(themedSharedStyles, theme);
62
160
  const handleClick = () => {
63
161
  if (!disabled && onChange) {
64
162
  onChange(!checked);
65
163
  }
66
164
  };
67
165
  const handleChange = () => {};
68
- const stateStyles = _generateStyles(checked, disabled, onChange !== undefined);
166
+ const stateStyles = _generateStyles(checked, onChange !== undefined, disabled, theme, themeName);
69
167
  let styledIcon;
70
168
  if (icon) {
71
- styledIcon = React__namespace.cloneElement(icon, _extends({
169
+ styledIcon = React__namespace.cloneElement(icon, {
72
170
  size: "small",
73
171
  style: [sharedStyles.icon, stateStyles.icon],
74
172
  "aria-hidden": true
75
- }, icon.props));
173
+ });
76
174
  }
77
- return React__namespace.createElement(wonderBlocksCore.UniqueIDProvider, {
78
- mockOnFirstRender: true,
79
- scope: "switch"
80
- }, ids => {
81
- const uniqueId = id || ids.get("switch");
82
- return React__namespace.createElement(wonderBlocksCore.View, {
83
- onClick: handleClick,
84
- style: [sharedStyles.switch, stateStyles.switch, disabled && sharedStyles.disabled],
85
- testId: testId
86
- }, React__namespace.createElement(StyledInput, {
87
- "aria-describedby": ariaDescribedBy,
88
- "aria-label": ariaLabel,
89
- "aria-labelledby": ariaLabelledBy,
90
- checked: checked,
91
- disabled: disabled,
92
- id: uniqueId,
93
- onChange: handleChange,
94
- ref: ref,
95
- role: "switch",
96
- style: sharedStyles.hidden,
97
- type: "checkbox"
98
- }), icon && styledIcon, React__namespace.createElement(StyledSpan, {
99
- style: [sharedStyles.slider, stateStyles.slider]
100
- }));
101
- });
175
+ return React__namespace.createElement(wonderBlocksCore.View, {
176
+ onClick: handleClick,
177
+ style: [sharedStyles.switch, stateStyles.switch, disabled && sharedStyles.disabled],
178
+ testId: testId
179
+ }, React__namespace.createElement(StyledInput, {
180
+ "aria-describedby": ariaDescribedBy,
181
+ "aria-label": ariaLabel,
182
+ "aria-labelledby": ariaLabelledBy,
183
+ checked: checked,
184
+ disabled: disabled,
185
+ id: uniqueId,
186
+ onChange: handleChange,
187
+ ref: ref,
188
+ role: "switch",
189
+ style: sharedStyles.hidden,
190
+ type: "checkbox"
191
+ }), icon && styledIcon, React__namespace.createElement(StyledSpan, {
192
+ style: [sharedStyles.slider, stateStyles.slider]
193
+ }));
102
194
  });
103
- const sharedStyles = aphrodite.StyleSheet.create({
195
+ const themedSharedStyles = theme => ({
104
196
  hidden: {
105
197
  opacity: 0,
106
- height: 0,
107
- width: 0
198
+ height: theme.size.height.none,
199
+ width: theme.size.width.none
108
200
  },
109
201
  switch: {
110
202
  display: "inline-flex",
111
- height: Spacing__default["default"].large_24,
112
- width: `calc(${Spacing__default["default"].xLarge_32}px + ${Spacing__default["default"].xSmall_8}px)`,
113
- borderRadius: Spacing__default["default"].small_12,
203
+ height: theme.size.height.large,
204
+ width: theme.size.width.large,
205
+ borderRadius: theme.border.radius.small,
114
206
  flexShrink: 0,
115
- cursor: "pointer",
116
207
  ":hover": {
117
- outlineOffset: 1
208
+ outlineOffset: theme.size.offset.default
118
209
  },
119
- transition: "background-color 0.15s ease-in-out"
210
+ ":focus-within": {
211
+ outline: `solid ${theme.size.width.small}px ${theme.color.outline.default}`,
212
+ outlineOffset: theme.size.offset.default
213
+ }
120
214
  },
121
215
  disabled: {
122
216
  cursor: "auto",
@@ -126,78 +220,75 @@ const sharedStyles = aphrodite.StyleSheet.create({
126
220
  },
127
221
  slider: {
128
222
  position: "absolute",
129
- top: Spacing__default["default"].xxxxSmall_2,
130
- left: Spacing__default["default"].xxxxSmall_2,
131
- height: `calc(${Spacing__default["default"].medium_16}px + ${Spacing__default["default"].xxxSmall_4}px)`,
132
- width: `calc(${Spacing__default["default"].medium_16}px + ${Spacing__default["default"].xxxSmall_4}px)`,
133
- borderRadius: "50%",
134
- backgroundColor: Color__default["default"].white,
135
- transition: "transform 0.15s ease-in-out"
223
+ top: theme.spacing.slider.position,
224
+ left: theme.spacing.slider.position,
225
+ height: theme.size.height.medium,
226
+ width: theme.size.width.medium,
227
+ borderRadius: theme.border.radius.full,
228
+ backgroundColor: theme.color.bg.slider.on,
229
+ transition: theme.spacing.transform.transition
136
230
  },
137
231
  icon: {
138
232
  position: "absolute",
139
- top: Spacing__default["default"].xxxSmall_4,
140
- left: Spacing__default["default"].xxxSmall_4,
233
+ top: theme.spacing.icon.position,
234
+ left: theme.spacing.icon.position,
141
235
  zIndex: 1,
142
- transition: "0.15s ease-in-out",
143
- transitionProperty: "transform, color"
236
+ transition: theme.spacing.transform.transition
144
237
  }
145
238
  });
146
239
  const styles = {};
147
- const _generateStyles = (checked, disabled, clickable) => {
148
- const checkedStyle = `${checked}-${disabled}-${clickable}`;
240
+ const _generateStyles = (checked, clickable, disabled, theme, themeName) => {
241
+ const checkedStyle = `${checked}-${clickable}-${disabled}-${themeName}`;
149
242
  if (styles[checkedStyle]) {
150
243
  return styles[checkedStyle];
151
244
  }
152
245
  let newStyles = {};
153
- const disabledBlue = Color.mix(Color__default["default"].blue, Color__default["default"].offBlack50);
154
- const activeBlue = Color.mix(Color__default["default"].offBlack32, Color__default["default"].blue);
246
+ const sharedSwitchStyles = {
247
+ cursor: clickable ? "pointer" : "auto",
248
+ ":hover": {
249
+ outline: clickable ? `solid ${theme.size.width.small}px ${theme.color.outline.default}` : "none"
250
+ }
251
+ };
155
252
  if (checked) {
156
253
  newStyles = {
157
- switch: {
158
- backgroundColor: disabled ? disabledBlue : Color__default["default"].blue,
254
+ switch: _extends({
255
+ backgroundColor: disabled ? theme.color.bg.switch.disabledOn : theme.color.bg.switch.on,
159
256
  ":active": {
160
- backgroundColor: !disabled && clickable && activeBlue
161
- },
162
- ":focus-within": {
163
- outline: `solid ${Spacing__default["default"].xxxxSmall_2}px ${Color__default["default"].blue}`,
164
- outlineOffset: 1
165
- },
166
- ":hover": {
167
- outline: clickable ? `solid ${Spacing__default["default"].xxxxSmall_2}px ${Color__default["default"].blue}` : "none"
257
+ backgroundColor: !disabled && clickable ? theme.color.bg.switch.activeOn : undefined
168
258
  }
169
- },
259
+ }, sharedSwitchStyles),
170
260
  slider: {
171
- transform: `translateX(${Spacing__default["default"].medium_16}px)`
261
+ transform: theme.spacing.transform.default
172
262
  },
173
263
  icon: {
174
- color: disabled ? disabledBlue : Color__default["default"].blue,
175
- transform: `translateX(${Spacing__default["default"].medium_16}px)`
264
+ color: disabled ? theme.color.bg.icon.disabledOn : theme.color.bg.icon.on,
265
+ transform: theme.spacing.transform.default
176
266
  }
177
267
  };
178
268
  } else {
179
269
  newStyles = {
180
- switch: {
181
- backgroundColor: disabled ? Color__default["default"].offBlack32 : Color__default["default"].offBlack50,
270
+ switch: _extends({
271
+ backgroundColor: disabled ? theme.color.bg.switch.disabledOff : theme.color.bg.switch.off,
182
272
  ":active": {
183
- backgroundColor: !disabled && clickable && Color__default["default"].offBlack64
184
- },
185
- ":focus-within": {
186
- outline: `solid ${Spacing__default["default"].xxxxSmall_2}px ${Color__default["default"].blue}`,
187
- outlineOffset: 1
188
- },
189
- ":hover": {
190
- outline: clickable ? `solid ${Spacing__default["default"].xxxxSmall_2}px ${Color__default["default"].blue}` : "none"
273
+ backgroundColor: !disabled && clickable ? theme.color.bg.switch.activeOff : undefined
191
274
  }
275
+ }, sharedSwitchStyles),
276
+ slider: {
277
+ backgroundColor: theme.color.bg.slider.off
192
278
  },
193
279
  icon: {
194
- color: disabled ? Color__default["default"].offBlack32 : Color__default["default"].offBlack50
280
+ color: disabled ? theme.color.bg.icon.disabledOff : theme.color.bg.icon.off
195
281
  }
196
282
  };
197
283
  }
198
284
  styles[checkedStyle] = aphrodite.StyleSheet.create(newStyles);
199
285
  return styles[checkedStyle];
200
286
  };
287
+ const Switch = React__namespace.forwardRef(function Switch(props, ref) {
288
+ return React__namespace.createElement(ThemedSwitch, null, React__namespace.createElement(SwitchCore, _extends({}, props, {
289
+ ref: ref
290
+ })));
291
+ });
201
292
  Switch.displayName = "Switch";
202
293
 
203
294
  module.exports = Switch;
@@ -0,0 +1,62 @@
1
+ declare const theme: {
2
+ color: {
3
+ bg: {
4
+ switch: {
5
+ off: string;
6
+ disabledOff: string;
7
+ activeOff: string;
8
+ on: string;
9
+ disabledOn: string;
10
+ activeOn: string;
11
+ };
12
+ slider: {
13
+ on: string;
14
+ off: string;
15
+ };
16
+ icon: {
17
+ on: string;
18
+ disabledOn: string;
19
+ off: string;
20
+ disabledOff: string;
21
+ };
22
+ };
23
+ outline: {
24
+ default: string;
25
+ };
26
+ };
27
+ border: {
28
+ radius: {
29
+ small: 12;
30
+ full: string;
31
+ };
32
+ };
33
+ size: {
34
+ height: {
35
+ none: number;
36
+ medium: number;
37
+ large: 24;
38
+ };
39
+ width: {
40
+ none: number;
41
+ small: 2;
42
+ medium: number;
43
+ large: number;
44
+ };
45
+ offset: {
46
+ default: number;
47
+ };
48
+ };
49
+ spacing: {
50
+ slider: {
51
+ position: 2;
52
+ };
53
+ icon: {
54
+ position: 4;
55
+ };
56
+ transform: {
57
+ default: string;
58
+ transition: string;
59
+ };
60
+ };
61
+ };
62
+ export default theme;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * The overrides for khanmigo theme for a switch.
3
+ */
4
+ declare const theme: {
5
+ color: {
6
+ bg: {
7
+ switch: {
8
+ off: string;
9
+ disabledOff: string;
10
+ activeOff: string;
11
+ on: string;
12
+ disabledOn: string;
13
+ activeOn: string;
14
+ };
15
+ slider: {
16
+ on: string;
17
+ off: string;
18
+ };
19
+ icon: {
20
+ on: string;
21
+ disabledOn: string;
22
+ off: string;
23
+ disabledOff: string;
24
+ };
25
+ };
26
+ outline: {
27
+ default: string;
28
+ };
29
+ };
30
+ border: {
31
+ radius: {
32
+ small: 12;
33
+ full: string;
34
+ };
35
+ };
36
+ size: {
37
+ height: {
38
+ none: number;
39
+ medium: number;
40
+ large: 24;
41
+ };
42
+ width: {
43
+ none: number;
44
+ small: 2;
45
+ medium: number;
46
+ large: number;
47
+ };
48
+ offset: {
49
+ default: number;
50
+ };
51
+ };
52
+ spacing: {
53
+ slider: {
54
+ position: 2;
55
+ };
56
+ icon: {
57
+ position: 4;
58
+ };
59
+ transform: {
60
+ default: string;
61
+ transition: string;
62
+ };
63
+ };
64
+ };
65
+ export default theme;
@@ -0,0 +1,80 @@
1
+ import * as React from "react";
2
+ import defaultTheme from "./default";
3
+ type Props = {
4
+ children: React.ReactNode;
5
+ };
6
+ export type SwitchThemeContract = typeof defaultTheme;
7
+ /**
8
+ * The context that provides the theme to the Switch component.
9
+ * This is generally consumed via the `useScopedTheme` hook.
10
+ */
11
+ export declare const SwitchThemeContext: React.Context<{
12
+ color: {
13
+ bg: {
14
+ switch: {
15
+ off: string;
16
+ disabledOff: string;
17
+ activeOff: string;
18
+ on: string;
19
+ disabledOn: string;
20
+ activeOn: string;
21
+ };
22
+ slider: {
23
+ /**
24
+ * The context that provides the theme to the Switch component.
25
+ * This is generally consumed via the `useScopedTheme` hook.
26
+ */
27
+ on: string;
28
+ off: string;
29
+ };
30
+ icon: {
31
+ on: string;
32
+ disabledOn: string;
33
+ off: string;
34
+ disabledOff: string;
35
+ };
36
+ };
37
+ outline: {
38
+ default: string;
39
+ };
40
+ };
41
+ border: {
42
+ radius: {
43
+ small: 12;
44
+ full: string;
45
+ };
46
+ };
47
+ size: {
48
+ height: {
49
+ none: number;
50
+ medium: number;
51
+ large: 24;
52
+ };
53
+ width: {
54
+ none: number;
55
+ small: 2;
56
+ medium: number;
57
+ large: number;
58
+ };
59
+ offset: {
60
+ default: number;
61
+ };
62
+ };
63
+ spacing: {
64
+ slider: {
65
+ position: 2;
66
+ };
67
+ icon: {
68
+ position: 4;
69
+ };
70
+ transform: {
71
+ default: string;
72
+ transition: string;
73
+ };
74
+ };
75
+ }>;
76
+ /**
77
+ * ThemedSwitch is a component that provides a theme to the <Switch/> component.
78
+ */
79
+ export default function ThemedSwitch(props: Props): JSX.Element;
80
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-switch",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "design": "v1",
5
5
  "description": "Switch components for Wonder Blocks.",
6
6
  "main": "dist/index.js",
@@ -16,10 +16,9 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@babel/runtime": "^7.18.6",
19
- "@khanacademy/wonder-blocks-color": "^2.0.1",
20
- "@khanacademy/wonder-blocks-core": "^6.1.1",
21
- "@khanacademy/wonder-blocks-icon": "^2.1.5",
22
- "@khanacademy/wonder-blocks-spacing": "^4.0.1"
19
+ "@khanacademy/wonder-blocks-core": "^6.2.0",
20
+ "@khanacademy/wonder-blocks-icon": "^2.1.6",
21
+ "@khanacademy/wonder-blocks-theming": "^1.1.0"
23
22
  },
24
23
  "peerDependencies": {
25
24
  "aphrodite": "^1.2.5",
@@ -3,6 +3,7 @@ import {render, screen} from "@testing-library/react";
3
3
 
4
4
  import userEvent from "@testing-library/user-event";
5
5
  import Icon, {icons} from "@khanacademy/wonder-blocks-icon";
6
+ import {RenderStateRoot} from "@khanacademy/wonder-blocks-core";
6
7
  import Switch from "../switch";
7
8
 
8
9
  describe("Switch", () => {
@@ -10,7 +11,11 @@ describe("Switch", () => {
10
11
  test("clicking the switch should call onChange", () => {
11
12
  // Arrange
12
13
  const onChangeSpy = jest.fn();
13
- render(<Switch checked={false} onChange={onChangeSpy} />);
14
+ render(
15
+ <RenderStateRoot>
16
+ <Switch checked={false} onChange={onChangeSpy} />
17
+ </RenderStateRoot>,
18
+ );
14
19
 
15
20
  // Act
16
21
  const switchComponent = screen.getByRole("switch");
@@ -24,11 +29,13 @@ describe("Switch", () => {
24
29
  // Arrange
25
30
  const onChangeSpy = jest.fn();
26
31
  render(
27
- <Switch
28
- checked={false}
29
- onChange={onChangeSpy}
30
- disabled={true}
31
- />,
32
+ <RenderStateRoot>
33
+ <Switch
34
+ checked={false}
35
+ onChange={onChangeSpy}
36
+ disabled={true}
37
+ />
38
+ </RenderStateRoot>,
32
39
  );
33
40
 
34
41
  // Act
@@ -42,7 +49,11 @@ describe("Switch", () => {
42
49
  test("pressing the space key should call onChange", () => {
43
50
  // Arrange
44
51
  const onChangeSpy = jest.fn();
45
- render(<Switch checked={false} onChange={onChangeSpy} />);
52
+ render(
53
+ <RenderStateRoot>
54
+ <Switch checked={false} onChange={onChangeSpy} />
55
+ </RenderStateRoot>,
56
+ );
46
57
 
47
58
  // Act
48
59
  const switchComponent = screen.getByRole("switch");
@@ -57,14 +68,14 @@ describe("Switch", () => {
57
68
  // Arrange
58
69
  const onChangeSpy = jest.fn();
59
70
  render(
60
- <>
71
+ <RenderStateRoot>
61
72
  <Switch
62
73
  id="switch-id"
63
74
  checked={false}
64
75
  onChange={onChangeSpy}
65
76
  />
66
77
  <label htmlFor="switch-id">Switch</label>
67
- </>,
78
+ </RenderStateRoot>,
68
79
  );
69
80
 
70
81
  // Act
@@ -80,7 +91,13 @@ describe("Switch", () => {
80
91
  it("should set the accessibility attributes accordingly", () => {
81
92
  // Arrange
82
93
  render(
83
- <Switch aria-label="Gravity" checked={true} disabled={true} />,
94
+ <RenderStateRoot>
95
+ <Switch
96
+ aria-label="Gravity"
97
+ checked={true}
98
+ disabled={true}
99
+ />
100
+ </RenderStateRoot>,
84
101
  );
85
102
 
86
103
  // Act
@@ -94,10 +111,12 @@ describe("Switch", () => {
94
111
  it("should render an icon if one is provided", () => {
95
112
  // Arrange
96
113
  render(
97
- <Switch
98
- checked={false}
99
- icon={<Icon icon={icons.add} testId="test-icon" />}
100
- />,
114
+ <RenderStateRoot>
115
+ <Switch
116
+ checked={false}
117
+ icon={<Icon icon={icons.add} testId="test-icon" />}
118
+ />
119
+ </RenderStateRoot>,
101
120
  );
102
121
 
103
122
  // Act