@khanacademy/wonder-blocks-icon-button 6.1.3 → 7.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @khanacademy/wonder-blocks-icon-button
2
2
 
3
+ ## 7.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - 61f7837: Remove `light` variant, and replace it with `actionStyles.inverse` for one-off cases
8
+ - 3cacbe7: Rename `color` prop to `actionType`. Also rename the `default` value to `progressive`.
9
+
10
+ ### Patch Changes
11
+
12
+ - 86e1901: Update IconButton to use `box-shadow` instead of `outline`. Also removed the negative margins around the icon button.
13
+ - 4887c59: Use `focus` styles from `wonder-blocks-styles` to match the global focus outline.
14
+ - Updated dependencies [aace76a]
15
+ - Updated dependencies [61f7837]
16
+ - @khanacademy/wonder-blocks-styles@0.2.0
17
+
18
+ ## 6.1.4
19
+
20
+ ### Patch Changes
21
+
22
+ - 999101f: Fix IconButton theme to use semanticColor.icon tokens
23
+ - 1d7be37: Use pnpm catalog to pin dependency versions across packages
24
+ - Updated dependencies [1d7be37]
25
+ - Updated dependencies [999101f]
26
+ - @khanacademy/wonder-blocks-clickable@6.1.4
27
+ - @khanacademy/wonder-blocks-theming@3.2.1
28
+ - @khanacademy/wonder-blocks-core@12.2.1
29
+ - @khanacademy/wonder-blocks-icon@5.1.3
30
+ - @khanacademy/wonder-blocks-tokens@5.1.1
31
+
3
32
  ## 6.1.3
4
33
 
5
34
  ### Patch Changes
@@ -3,6 +3,7 @@ import type { PhosphorIconAsset } from "@khanacademy/wonder-blocks-icon";
3
3
  import type { AriaProps, StyleType } from "@khanacademy/wonder-blocks-core";
4
4
  import { Link } from "react-router-dom";
5
5
  export type IconButtonSize = "xsmall" | "small" | "medium" | "large";
6
+ export type IconButtonActionType = "progressive" | "destructive";
6
7
  export type SharedProps = Partial<Omit<AriaProps, "aria-disabled">> & {
7
8
  /**
8
9
  * A unique identifier for the IconButton.
@@ -13,9 +14,15 @@ export type SharedProps = Partial<Omit<AriaProps, "aria-disabled">> & {
13
14
  */
14
15
  icon: PhosphorIconAsset;
15
16
  /**
16
- * The color of the icon button, either blue or red.
17
+ * The action type/category of the icon button.
18
+ *
19
+ * - `progressive` is used for actions that move the user forward in a flow.
20
+ * - `destructive` is used for actions that have a negative impact on the
21
+ * user.
22
+ *
23
+ * Defaults to `progressive`.
17
24
  */
18
- color?: "default" | "destructive";
25
+ actionType?: IconButtonActionType;
19
26
  /**
20
27
  * The kind of the icon button, either primary, secondary, or tertiary.
21
28
  *
@@ -27,10 +34,6 @@ export type SharedProps = Partial<Omit<AriaProps, "aria-disabled">> & {
27
34
  * In the hover/focus/press states, all variants have a border.
28
35
  */
29
36
  kind?: "primary" | "secondary" | "tertiary";
30
- /**
31
- * Whether the icon button is on a dark/colored background.
32
- */
33
- light?: boolean;
34
37
  /**
35
38
  * Whether the icon button is disabled.
36
39
  */
package/dist/es/index.js CHANGED
@@ -8,7 +8,8 @@ import { addStyle } from '@khanacademy/wonder-blocks-core';
8
8
  import { isClientSideUrl } from '@khanacademy/wonder-blocks-clickable';
9
9
  import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
10
10
  import { mergeTheme, createThemeContext, ThemeSwitcherContext, useScopedTheme } from '@khanacademy/wonder-blocks-theming';
11
- import { semanticColor, color, border } from '@khanacademy/wonder-blocks-tokens';
11
+ import { focusStyles } from '@khanacademy/wonder-blocks-styles';
12
+ import { semanticColor, border } from '@khanacademy/wonder-blocks-tokens';
12
13
 
13
14
  const iconSizeForButtonSize = size => {
14
15
  switch (size) {
@@ -34,24 +35,15 @@ const disabledStates = {
34
35
  background: "transparent",
35
36
  foreground: semanticColor.action.secondary.disabled.foreground
36
37
  };
37
- const disabledLightStates = {
38
- border: color.white50,
39
- background: "transparent",
40
- foreground: color.white50
41
- };
42
- const focusOutline = {
43
- border: semanticColor.focus.outer
44
- };
45
- const focusOutlineLight = {
46
- border: semanticColor.border.inverse
47
- };
48
38
  const baseColorStates = _extends({}, semanticColor.action.secondary, {
49
39
  progressive: _extends({}, semanticColor.action.secondary.progressive, {
50
40
  default: _extends({}, semanticColor.action.secondary.progressive.default, {
51
41
  border: "transparent",
52
42
  background: "transparent"
53
43
  }),
54
- focus: focusOutline,
44
+ hover: _extends({}, semanticColor.action.secondary.progressive.hover, {
45
+ background: "transparent"
46
+ }),
55
47
  press: {
56
48
  border: semanticColor.action.secondary.progressive.press.border,
57
49
  background: "transparent",
@@ -63,7 +55,9 @@ const baseColorStates = _extends({}, semanticColor.action.secondary, {
63
55
  border: "transparent",
64
56
  background: "transparent"
65
57
  }),
66
- focus: focusOutline,
58
+ hover: _extends({}, semanticColor.action.secondary.destructive.hover, {
59
+ background: "transparent"
60
+ }),
67
61
  press: {
68
62
  border: semanticColor.action.secondary.destructive.press.border,
69
63
  background: "transparent",
@@ -72,57 +66,13 @@ const baseColorStates = _extends({}, semanticColor.action.secondary, {
72
66
  }),
73
67
  disabled: {
74
68
  default: disabledStates,
75
- focus: focusOutline,
76
69
  hover: disabledStates,
77
70
  press: disabledStates
78
- },
79
- disabledLight: {
80
- default: disabledLightStates,
81
- focus: focusOutlineLight,
82
- hover: disabledLightStates,
83
- press: disabledLightStates
84
71
  }
85
72
  });
86
73
  const theme$1 = {
87
74
  color: {
88
- primary: _extends({}, baseColorStates, {
89
- progressiveLight: {
90
- default: {
91
- border: semanticColor.border.inverse,
92
- background: "transparent",
93
- foreground: semanticColor.text.inverse
94
- },
95
- hover: {
96
- border: semanticColor.border.inverse,
97
- background: "transparent",
98
- foreground: semanticColor.text.inverse
99
- },
100
- focus: focusOutlineLight,
101
- press: {
102
- border: color.fadedBlue,
103
- background: "transparent",
104
- foreground: color.fadedBlue
105
- }
106
- },
107
- destructiveLight: {
108
- default: {
109
- border: semanticColor.border.inverse,
110
- background: "transparent",
111
- foreground: semanticColor.text.inverse
112
- },
113
- hover: {
114
- border: semanticColor.border.inverse,
115
- background: "transparent",
116
- foreground: semanticColor.text.inverse
117
- },
118
- focus: focusOutlineLight,
119
- press: {
120
- border: color.fadedRed,
121
- background: "transparent",
122
- foreground: color.fadedRed
123
- }
124
- }
125
- }),
75
+ primary: baseColorStates,
126
76
  secondary: _extends({}, baseColorStates, {
127
77
  progressive: _extends({}, baseColorStates.progressive, {
128
78
  default: _extends({}, baseColorStates.progressive.default, {
@@ -131,29 +81,27 @@ const theme$1 = {
131
81
  }),
132
82
  destructive: _extends({}, baseColorStates.destructive, {
133
83
  default: _extends({}, baseColorStates.destructive.default, {
134
- foreground: semanticColor.text.primary
84
+ foreground: semanticColor.icon.secondary
135
85
  })
136
86
  })
137
87
  }),
138
88
  tertiary: _extends({}, baseColorStates, {
139
89
  progressive: _extends({}, baseColorStates.progressive, {
140
90
  default: _extends({}, baseColorStates.progressive.default, {
141
- foreground: semanticColor.text.secondary
91
+ foreground: semanticColor.icon.primary
142
92
  })
143
93
  }),
144
94
  destructive: _extends({}, baseColorStates.destructive, {
145
95
  default: _extends({}, baseColorStates.destructive.default, {
146
- foreground: semanticColor.text.secondary
96
+ foreground: semanticColor.icon.primary
147
97
  })
148
98
  })
149
99
  })
150
100
  },
151
101
  border: {
152
102
  width: {
153
- default: border.width.thin,
154
- active: border.width.none,
155
- hovered: border.width.thin,
156
- hoveredInverse: border.width.thin
103
+ hover: border.width.thin,
104
+ press: border.width.thin
157
105
  },
158
106
  radius: {
159
107
  default: border.radius.medium_4
@@ -166,25 +114,12 @@ const primaryState = {
166
114
  foreground: semanticColor.khanmigo.primary
167
115
  }
168
116
  };
169
- const primaryLightState = {
170
- hover: {
171
- background: semanticColor.surface.primary,
172
- foreground: semanticColor.khanmigo.primary
173
- },
174
- press: {
175
- border: "transparent",
176
- background: color.white64,
177
- foreground: semanticColor.khanmigo.primary
178
- }
179
- };
180
117
  const actionType = semanticColor.action.primary;
181
118
  const theme = mergeTheme(theme$1, {
182
119
  color: {
183
120
  primary: {
184
121
  progressive: primaryState,
185
- destructive: primaryState,
186
- progressiveLight: primaryLightState,
187
- destructiveLight: primaryLightState
122
+ destructive: primaryState
188
123
  },
189
124
  secondary: {
190
125
  progressive: {
@@ -209,8 +144,7 @@ const theme = mergeTheme(theme$1, {
209
144
  },
210
145
  border: {
211
146
  width: {
212
- hovered: border.width.none,
213
- hoveredInverse: border.width.none
147
+ hover: border.width.none
214
148
  }
215
149
  }
216
150
  });
@@ -229,7 +163,7 @@ function ThemedIconButton(props) {
229
163
  }, props.children);
230
164
  }
231
165
 
232
- const _excluded$1 = ["color", "disabled", "href", "icon", "kind", "light", "size", "skipClientNav", "style", "testId", "type"];
166
+ const _excluded$1 = ["actionType", "disabled", "href", "icon", "kind", "size", "skipClientNav", "style", "testId", "type"];
233
167
  function IconChooser({
234
168
  icon,
235
169
  size
@@ -256,12 +190,11 @@ const StyledButton = addStyle("button");
256
190
  const StyledLink = addStyle(Link);
257
191
  const IconButtonCore = React.forwardRef(function IconButtonCore(props, ref) {
258
192
  const {
259
- color,
193
+ actionType,
260
194
  disabled,
261
195
  href,
262
196
  icon,
263
197
  kind = "primary",
264
- light = false,
265
198
  size = "medium",
266
199
  skipClientNav,
267
200
  style,
@@ -274,7 +207,7 @@ const IconButtonCore = React.forwardRef(function IconButtonCore(props, ref) {
274
207
  themeName
275
208
  } = useScopedTheme(IconButtonThemeContext);
276
209
  const renderInner = router => {
277
- const buttonStyles = _generateStyles(color, !!disabled, kind, light, size, theme, themeName);
210
+ const buttonStyles = _generateStyles(actionType, !!disabled, kind, size, theme, themeName);
278
211
  const defaultStyle = [sharedStyles.shared, buttonStyles.default, disabled && buttonStyles.disabled];
279
212
  const child = React.createElement(IconChooser, {
280
213
  size: size,
@@ -317,58 +250,44 @@ const sharedStyles = StyleSheet.create({
317
250
  outline: "none",
318
251
  textDecoration: "none",
319
252
  background: "none",
320
- margin: -8,
253
+ margin: 0,
321
254
  touchAction: "manipulation"
322
255
  }
323
256
  });
324
257
  const styles = {};
325
- function getActionType(buttonColor, disabled) {
326
- const actionType = buttonColor === "destructive" ? "destructive" : "progressive";
327
- if (disabled) {
328
- return "disabled";
329
- }
330
- return actionType;
331
- }
332
- function getStylesByKind(buttonColor, disabled, kind, light, theme) {
333
- let actionType = getActionType(buttonColor, disabled);
334
- const themeVariant = theme.color[kind][actionType];
258
+ function getStylesByKind(actionType = "progressive", disabled, kind, theme) {
259
+ const actionTypeOrDisabled = disabled ? "disabled" : actionType;
260
+ const themeVariant = theme.color[kind][actionTypeOrDisabled];
335
261
  if (kind === "primary") {
336
- if (light) {
337
- actionType = `${actionType}Light`;
338
- }
339
- const _themeVariant = theme.color[kind][actionType];
340
- return {
262
+ return _extends({
341
263
  default: {
342
- borderColor: _themeVariant.default.border,
343
- background: _themeVariant.default.background,
344
- color: _themeVariant.default.foreground
264
+ borderColor: themeVariant.default.border,
265
+ background: themeVariant.default.background,
266
+ color: themeVariant.default.foreground
345
267
  },
346
268
  ":hover": {
347
- background: _themeVariant.hover.background,
348
- color: _themeVariant.hover.foreground,
349
- outlineColor: _themeVariant.hover.border,
350
- outlineOffset: 1,
351
- outlineStyle: "solid",
352
- outlineWidth: light ? theme.border.width.hoveredInverse : theme.border.width.hovered
353
- },
354
- ":focus-visible": {
355
- outlineColor: _themeVariant.focus.border
356
- },
269
+ background: themeVariant.hover.background,
270
+ color: themeVariant.hover.foreground,
271
+ borderColor: themeVariant.hover.border,
272
+ borderStyle: "solid",
273
+ borderWidth: theme.border.width.hover
274
+ }
275
+ }, focusStyles.focus, {
357
276
  ":active": {
358
- borderColor: _themeVariant.press.border,
359
- background: _themeVariant.press.background,
360
- color: _themeVariant.press.foreground,
361
- outlineColor: _themeVariant.press.border
277
+ borderColor: themeVariant.press.border,
278
+ borderStyle: "solid",
279
+ borderWidth: theme.border.width.press,
280
+ background: themeVariant.press.background,
281
+ color: themeVariant.press.foreground
362
282
  },
363
283
  disabled: {
364
- background: _themeVariant.default.background,
365
- color: _themeVariant.default.foreground,
366
- outlineColor: _themeVariant.focus.border
284
+ background: themeVariant.default.background,
285
+ color: themeVariant.default.foreground
367
286
  }
368
- };
287
+ });
369
288
  }
370
289
  if (kind === "secondary" || kind === "tertiary") {
371
- return {
290
+ return _extends({
372
291
  default: {
373
292
  borderColor: themeVariant.default.border,
374
293
  background: themeVariant.default.background,
@@ -377,25 +296,19 @@ function getStylesByKind(buttonColor, disabled, kind, light, theme) {
377
296
  ":hover": {
378
297
  borderColor: themeVariant.hover.border,
379
298
  background: themeVariant.hover.background,
380
- color: themeVariant.hover.foreground,
381
- outlineWidth: theme.border.width.active
382
- },
383
- ":focus-visible": {
384
- outlineColor: themeVariant.focus.border
385
- },
299
+ color: themeVariant.hover.foreground
300
+ }
301
+ }, focusStyles.focus, {
386
302
  ":active": {
387
303
  borderColor: themeVariant.press.border,
388
304
  background: themeVariant.press.background,
389
- color: themeVariant.press.foreground,
390
- outlineColor: themeVariant.press.border,
391
- outlineWidth: theme.border.width.active
305
+ color: themeVariant.press.foreground
392
306
  },
393
307
  disabled: {
394
308
  background: themeVariant.default.background,
395
- color: themeVariant.default.foreground,
396
- outlineColor: themeVariant.focus.border
309
+ color: themeVariant.default.foreground
397
310
  }
398
- };
311
+ });
399
312
  }
400
313
  return {
401
314
  default: {},
@@ -405,16 +318,13 @@ function getStylesByKind(buttonColor, disabled, kind, light, theme) {
405
318
  disabled: {}
406
319
  };
407
320
  }
408
- const _generateStyles = (buttonColor = "default", disabled, kind, light, size, theme, themeName) => {
409
- const buttonType = `${buttonColor}-d_${disabled}-${kind}-l_${light}-${size}-${themeName}`;
321
+ const _generateStyles = (actionType = "progressive", disabled, kind, size, theme, themeName) => {
322
+ const buttonType = `${actionType}-d_${disabled}-${kind}-${size}-${themeName}`;
410
323
  if (styles[buttonType]) {
411
324
  return styles[buttonType];
412
325
  }
413
- if (light && kind !== "primary") {
414
- throw new Error("Light is only supported for primary IconButtons");
415
- }
416
326
  const pixelsForSize = targetPixelsForSize(size);
417
- const kindOverrides = getStylesByKind(buttonColor, disabled, kind, light, theme);
327
+ const kindOverrides = getStylesByKind(actionType, disabled, kind, theme);
418
328
  const disabledStatesStyles = kindOverrides.disabled;
419
329
  const newStyles = {
420
330
  default: _extends({
@@ -423,28 +333,18 @@ const _generateStyles = (buttonColor = "default", disabled, kind, light, size, t
423
333
  borderRadius: theme.border.radius.default
424
334
  }, kindOverrides.default, {
425
335
  ":hover": _extends({
426
- boxShadow: "none",
427
- borderRadius: theme.border.radius.default,
428
- outlineWidth: theme.border.width.default
336
+ borderRadius: theme.border.radius.default
429
337
  }, kindOverrides[":hover"]),
430
338
  ["@media not (hover: hover)"]: {
431
339
  ":hover": {
432
- boxShadow: "none",
433
340
  borderRadius: theme.border.radius.default,
434
- outline: "none",
435
341
  backgroundColor: "transparent"
436
342
  }
437
343
  },
438
344
  ":focus-visible": _extends({
439
- outlineWidth: theme.border.width.default,
440
- outlineOffset: 1,
441
- outlineStyle: "solid",
442
345
  borderRadius: theme.border.radius.default
443
346
  }, kindOverrides[":focus-visible"]),
444
347
  ":active": _extends({
445
- outlineWidth: theme.border.width.default,
446
- outlineOffset: 1,
447
- outlineStyle: "solid",
448
348
  borderRadius: theme.border.radius.default
449
349
  }, kindOverrides[":active"])
450
350
  }),
@@ -452,10 +352,10 @@ const _generateStyles = (buttonColor = "default", disabled, kind, light, size, t
452
352
  cursor: "not-allowed"
453
353
  }, disabledStatesStyles, {
454
354
  ":hover": _extends({}, disabledStatesStyles, {
455
- outline: "none"
355
+ border: "none"
456
356
  }),
457
357
  ":active": _extends({}, disabledStatesStyles, {
458
- outline: "none"
358
+ border: "none"
459
359
  }),
460
360
  ":focus-visible": disabledStatesStyles
461
361
  })
@@ -464,14 +364,13 @@ const _generateStyles = (buttonColor = "default", disabled, kind, light, size, t
464
364
  return styles[buttonType];
465
365
  };
466
366
 
467
- const _excluded = ["color", "disabled", "href", "kind", "light", "size", "skipClientNav", "tabIndex", "target", "type"];
367
+ const _excluded = ["actionType", "disabled", "href", "kind", "size", "skipClientNav", "tabIndex", "target", "type"];
468
368
  const IconButton = React.forwardRef(function IconButton(props, ref) {
469
369
  const {
470
- color = "default",
370
+ actionType = "progressive",
471
371
  disabled = false,
472
372
  href,
473
373
  kind = "primary",
474
- light = false,
475
374
  size = "medium",
476
375
  skipClientNav,
477
376
  tabIndex,
@@ -494,11 +393,10 @@ const IconButton = React.forwardRef(function IconButton(props, ref) {
494
393
  }
495
394
  }
496
395
  return React.createElement(ThemedIconButton, null, React.createElement(IconButtonCore, _extends({}, sharedProps, {
497
- color: color,
396
+ actionType: actionType,
498
397
  disabled: disabled,
499
398
  href: href,
500
399
  kind: kind,
501
- light: light,
502
400
  ref: ref,
503
401
  skipClientNav: skipClientNav,
504
402
  size: size,