@khanacademy/wonder-blocks-icon-button 4.1.9 → 4.2.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,16 @@
1
1
  # @khanacademy/wonder-blocks-icon-button
2
2
 
3
+ ## 4.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fb704043: Add size prop to icon button
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [80cab317]
12
+ - @khanacademy/wonder-blocks-clickable@4.0.7
13
+
3
14
  ## 4.1.9
4
15
 
5
16
  ### Patch Changes
@@ -2,6 +2,7 @@ import * as React from "react";
2
2
  import type { IconAsset } 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
+ export type IconButtonSize = "xsmall" | "small" | "medium";
5
6
  export type SharedProps = Partial<Omit<AriaProps, "aria-disabled">> & {
6
7
  /**
7
8
  * A Wonder Blocks icon asset, an object specifing paths for one or more of
@@ -35,6 +36,12 @@ export type SharedProps = Partial<Omit<AriaProps, "aria-disabled">> & {
35
36
  * Test ID used for e2e testing.
36
37
  */
37
38
  testId?: string;
39
+ /**
40
+ * Size of the icon button.
41
+ * One of `xsmall` (16 icon, 20 target), `small` (24, 32), or `medium (24, 40).
42
+ * Defaults to `medium`.
43
+ */
44
+ size?: IconButtonSize;
38
45
  /**
39
46
  * Optional custom styles.
40
47
  */
package/dist/es/index.js CHANGED
@@ -39,13 +39,28 @@ function _objectWithoutPropertiesLoose(source, excluded) {
39
39
  return target;
40
40
  }
41
41
 
42
- const _excluded$1 = ["skipClientNav", "color", "disabled", "focused", "hovered", "href", "icon", "kind", "light", "pressed", "style", "testId", "waiting"];
42
+ const iconSizeForButtonSize = size => {
43
+ switch (size) {
44
+ case "xsmall":
45
+ return "small";
46
+ case "small":
47
+ return "medium";
48
+ case "medium":
49
+ return "medium";
50
+ }
51
+ };
52
+ const targetPixelsForSize = size => ({
53
+ xsmall: 24,
54
+ small: 32,
55
+ medium: 40
56
+ })[size];
57
+
58
+ const _excluded$1 = ["color", "disabled", "focused", "hovered", "href", "icon", "kind", "light", "pressed", "size", "skipClientNav", "style", "testId", "waiting"];
43
59
  const StyledAnchor = addStyle("a");
44
60
  const StyledButton = addStyle("button");
45
61
  const StyledLink = addStyle(Link);
46
62
  const IconButtonCore = React.forwardRef(function IconButtonCore(props, ref) {
47
63
  const {
48
- skipClientNav,
49
64
  color,
50
65
  disabled,
51
66
  focused,
@@ -55,16 +70,18 @@ const IconButtonCore = React.forwardRef(function IconButtonCore(props, ref) {
55
70
  kind = "primary",
56
71
  light = false,
57
72
  pressed,
73
+ size = "medium",
74
+ skipClientNav,
58
75
  style,
59
76
  testId
60
77
  } = props,
61
78
  restProps = _objectWithoutPropertiesLoose(props, _excluded$1);
62
79
  const renderInner = router => {
63
80
  const buttonColor = color === "destructive" ? SemanticColor.controlDestructive : SemanticColor.controlDefault;
64
- const buttonStyles = _generateStyles(buttonColor, kind, light);
65
- const defaultStyle = [sharedStyles.shared, disabled && sharedStyles.disabled, buttonStyles.default, disabled && buttonStyles.disabled, !disabled && (pressed ? buttonStyles.active : (hovered || focused) && buttonStyles.focus)];
81
+ const buttonStyles = _generateStyles(buttonColor, kind, light, size);
82
+ const defaultStyle = [sharedStyles.shared, buttonStyles.default, disabled && buttonStyles.disabled, !disabled && (pressed ? buttonStyles.active : (hovered || focused) && buttonStyles.focus)];
66
83
  const child = React.createElement(Icon, {
67
- size: "medium",
84
+ size: iconSizeForButtonSize(size),
68
85
  color: "currentColor",
69
86
  icon: icon
70
87
  });
@@ -98,8 +115,6 @@ const sharedStyles = StyleSheet.create({
98
115
  alignItems: "center",
99
116
  justifyContent: "center",
100
117
  boxSizing: "border-box",
101
- height: 40,
102
- width: 40,
103
118
  padding: 0,
104
119
  cursor: "pointer",
105
120
  border: "none",
@@ -111,14 +126,11 @@ const sharedStyles = StyleSheet.create({
111
126
  ":focus": {
112
127
  WebkitTapHighlightColor: "rgba(0,0,0,0)"
113
128
  }
114
- },
115
- disabled: {
116
- cursor: "default"
117
129
  }
118
130
  });
119
131
  const styles = {};
120
- const _generateStyles = (color, kind, light) => {
121
- const buttonType = color + kind + light.toString();
132
+ const _generateStyles = (color, kind, light, size) => {
133
+ const buttonType = `${color}-${kind}-${light}-${size}`;
122
134
  if (styles[buttonType]) {
123
135
  return styles[buttonType];
124
136
  }
@@ -131,8 +143,25 @@ const _generateStyles = (color, kind, light) => {
131
143
  offBlack64,
132
144
  offBlack
133
145
  } = Color;
146
+ const defaultColor = (() => {
147
+ switch (kind) {
148
+ case "primary":
149
+ return light ? white : color;
150
+ case "secondary":
151
+ return offBlack;
152
+ case "tertiary":
153
+ return offBlack64;
154
+ default:
155
+ throw new Error("IconButton kind not recognized");
156
+ }
157
+ })();
158
+ const pixelsForSize = targetPixelsForSize(size);
134
159
  const newStyles = {
135
- default: {},
160
+ default: {
161
+ height: pixelsForSize,
162
+ width: pixelsForSize,
163
+ color: defaultColor
164
+ },
136
165
  focus: {
137
166
  color: light ? white : color,
138
167
  borderWidth: 2,
@@ -152,37 +181,23 @@ const _generateStyles = (color, kind, light) => {
152
181
  cursor: "default"
153
182
  }
154
183
  };
155
- if (kind === "primary") {
156
- newStyles["default"] = {
157
- color: light ? white : color
158
- };
159
- } else if (kind === "secondary") {
160
- newStyles["default"] = {
161
- color: offBlack
162
- };
163
- } else if (kind === "tertiary") {
164
- newStyles["default"] = {
165
- color: offBlack64
166
- };
167
- } else {
168
- throw new Error("IconButton kind not recognized");
169
- }
170
184
  styles[buttonType] = StyleSheet.create(newStyles);
171
185
  return styles[buttonType];
172
186
  };
173
187
 
174
- const _excluded = ["onClick", "href", "skipClientNav", "tabIndex", "target", "color", "kind", "light", "disabled"];
188
+ const _excluded = ["color", "disabled", "href", "kind", "light", "onClick", "size", "skipClientNav", "tabIndex", "target"];
175
189
  const IconButton = React.forwardRef(function IconButton(props, ref) {
176
190
  const {
177
- onClick,
178
- href,
179
- skipClientNav,
180
- tabIndex,
181
- target,
182
191
  color = "default",
192
+ disabled = false,
193
+ href,
183
194
  kind = "primary",
184
195
  light = false,
185
- disabled = false
196
+ onClick,
197
+ size = "medium",
198
+ skipClientNav,
199
+ tabIndex,
200
+ target
186
201
  } = props,
187
202
  sharedProps = _objectWithoutPropertiesLoose(props, _excluded);
188
203
  const renderClickableBehavior = router => {
@@ -197,14 +212,15 @@ const IconButton = React.forwardRef(function IconButton(props, ref) {
197
212
  let childrenProps = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
198
213
  return React.createElement(IconButtonCore, _extends({}, sharedProps, state, childrenProps, {
199
214
  color: color,
215
+ disabled: disabled,
216
+ href: href,
200
217
  kind: kind,
201
218
  light: light,
202
- disabled: disabled,
219
+ ref: ref,
203
220
  skipClientNav: skipClientNav,
204
- href: href,
221
+ size: size,
205
222
  target: target,
206
- tabIndex: tabIndex,
207
- ref: ref
223
+ tabIndex: tabIndex
208
224
  }));
209
225
  });
210
226
  };
package/dist/index.js CHANGED
@@ -65,13 +65,28 @@ function _objectWithoutPropertiesLoose(source, excluded) {
65
65
  return target;
66
66
  }
67
67
 
68
- const _excluded$1 = ["skipClientNav", "color", "disabled", "focused", "hovered", "href", "icon", "kind", "light", "pressed", "style", "testId", "waiting"];
68
+ const iconSizeForButtonSize = size => {
69
+ switch (size) {
70
+ case "xsmall":
71
+ return "small";
72
+ case "small":
73
+ return "medium";
74
+ case "medium":
75
+ return "medium";
76
+ }
77
+ };
78
+ const targetPixelsForSize = size => ({
79
+ xsmall: 24,
80
+ small: 32,
81
+ medium: 40
82
+ })[size];
83
+
84
+ const _excluded$1 = ["color", "disabled", "focused", "hovered", "href", "icon", "kind", "light", "pressed", "size", "skipClientNav", "style", "testId", "waiting"];
69
85
  const StyledAnchor = wonderBlocksCore.addStyle("a");
70
86
  const StyledButton = wonderBlocksCore.addStyle("button");
71
87
  const StyledLink = wonderBlocksCore.addStyle(reactRouterDom.Link);
72
88
  const IconButtonCore = React__namespace.forwardRef(function IconButtonCore(props, ref) {
73
89
  const {
74
- skipClientNav,
75
90
  color,
76
91
  disabled,
77
92
  focused,
@@ -81,16 +96,18 @@ const IconButtonCore = React__namespace.forwardRef(function IconButtonCore(props
81
96
  kind = "primary",
82
97
  light = false,
83
98
  pressed,
99
+ size = "medium",
100
+ skipClientNav,
84
101
  style,
85
102
  testId
86
103
  } = props,
87
104
  restProps = _objectWithoutPropertiesLoose(props, _excluded$1);
88
105
  const renderInner = router => {
89
106
  const buttonColor = color === "destructive" ? Color.SemanticColor.controlDestructive : Color.SemanticColor.controlDefault;
90
- const buttonStyles = _generateStyles(buttonColor, kind, light);
91
- const defaultStyle = [sharedStyles.shared, disabled && sharedStyles.disabled, buttonStyles.default, disabled && buttonStyles.disabled, !disabled && (pressed ? buttonStyles.active : (hovered || focused) && buttonStyles.focus)];
107
+ const buttonStyles = _generateStyles(buttonColor, kind, light, size);
108
+ const defaultStyle = [sharedStyles.shared, buttonStyles.default, disabled && buttonStyles.disabled, !disabled && (pressed ? buttonStyles.active : (hovered || focused) && buttonStyles.focus)];
92
109
  const child = React__namespace.createElement(Icon__default["default"], {
93
- size: "medium",
110
+ size: iconSizeForButtonSize(size),
94
111
  color: "currentColor",
95
112
  icon: icon
96
113
  });
@@ -124,8 +141,6 @@ const sharedStyles = aphrodite.StyleSheet.create({
124
141
  alignItems: "center",
125
142
  justifyContent: "center",
126
143
  boxSizing: "border-box",
127
- height: 40,
128
- width: 40,
129
144
  padding: 0,
130
145
  cursor: "pointer",
131
146
  border: "none",
@@ -137,14 +152,11 @@ const sharedStyles = aphrodite.StyleSheet.create({
137
152
  ":focus": {
138
153
  WebkitTapHighlightColor: "rgba(0,0,0,0)"
139
154
  }
140
- },
141
- disabled: {
142
- cursor: "default"
143
155
  }
144
156
  });
145
157
  const styles = {};
146
- const _generateStyles = (color, kind, light) => {
147
- const buttonType = color + kind + light.toString();
158
+ const _generateStyles = (color, kind, light, size) => {
159
+ const buttonType = `${color}-${kind}-${light}-${size}`;
148
160
  if (styles[buttonType]) {
149
161
  return styles[buttonType];
150
162
  }
@@ -157,8 +169,25 @@ const _generateStyles = (color, kind, light) => {
157
169
  offBlack64,
158
170
  offBlack
159
171
  } = Color__default["default"];
172
+ const defaultColor = (() => {
173
+ switch (kind) {
174
+ case "primary":
175
+ return light ? white : color;
176
+ case "secondary":
177
+ return offBlack;
178
+ case "tertiary":
179
+ return offBlack64;
180
+ default:
181
+ throw new Error("IconButton kind not recognized");
182
+ }
183
+ })();
184
+ const pixelsForSize = targetPixelsForSize(size);
160
185
  const newStyles = {
161
- default: {},
186
+ default: {
187
+ height: pixelsForSize,
188
+ width: pixelsForSize,
189
+ color: defaultColor
190
+ },
162
191
  focus: {
163
192
  color: light ? white : color,
164
193
  borderWidth: 2,
@@ -178,37 +207,23 @@ const _generateStyles = (color, kind, light) => {
178
207
  cursor: "default"
179
208
  }
180
209
  };
181
- if (kind === "primary") {
182
- newStyles["default"] = {
183
- color: light ? white : color
184
- };
185
- } else if (kind === "secondary") {
186
- newStyles["default"] = {
187
- color: offBlack
188
- };
189
- } else if (kind === "tertiary") {
190
- newStyles["default"] = {
191
- color: offBlack64
192
- };
193
- } else {
194
- throw new Error("IconButton kind not recognized");
195
- }
196
210
  styles[buttonType] = aphrodite.StyleSheet.create(newStyles);
197
211
  return styles[buttonType];
198
212
  };
199
213
 
200
- const _excluded = ["onClick", "href", "skipClientNav", "tabIndex", "target", "color", "kind", "light", "disabled"];
214
+ const _excluded = ["color", "disabled", "href", "kind", "light", "onClick", "size", "skipClientNav", "tabIndex", "target"];
201
215
  const IconButton = React__namespace.forwardRef(function IconButton(props, ref) {
202
216
  const {
203
- onClick,
204
- href,
205
- skipClientNav,
206
- tabIndex,
207
- target,
208
217
  color = "default",
218
+ disabled = false,
219
+ href,
209
220
  kind = "primary",
210
221
  light = false,
211
- disabled = false
222
+ onClick,
223
+ size = "medium",
224
+ skipClientNav,
225
+ tabIndex,
226
+ target
212
227
  } = props,
213
228
  sharedProps = _objectWithoutPropertiesLoose(props, _excluded);
214
229
  const renderClickableBehavior = router => {
@@ -223,14 +238,15 @@ const IconButton = React__namespace.forwardRef(function IconButton(props, ref) {
223
238
  let childrenProps = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
224
239
  return React__namespace.createElement(IconButtonCore, _extends({}, sharedProps, state, childrenProps, {
225
240
  color: color,
241
+ disabled: disabled,
242
+ href: href,
226
243
  kind: kind,
227
244
  light: light,
228
- disabled: disabled,
245
+ ref: ref,
229
246
  skipClientNav: skipClientNav,
230
- href: href,
247
+ size: size,
231
248
  target: target,
232
- tabIndex: tabIndex,
233
- ref: ref
249
+ tabIndex: tabIndex
234
250
  }));
235
251
  });
236
252
  };
@@ -0,0 +1,10 @@
1
+ import { IconSize } from "@khanacademy/wonder-blocks-icon";
2
+ import { IconButtonSize } from "../components/icon-button";
3
+ /**
4
+ * A function that returns the icon size for a given icon button size.
5
+ */
6
+ export declare const iconSizeForButtonSize: (size: IconButtonSize) => IconSize;
7
+ /**
8
+ * A function that returns the size of the touch target in pixels for a given icon button size.
9
+ */
10
+ export declare const targetPixelsForSize: (size: IconButtonSize) => number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-icon-button",
3
- "version": "4.1.9",
3
+ "version": "4.2.0",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -16,7 +16,7 @@
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
18
  "@babel/runtime": "^7.18.6",
19
- "@khanacademy/wonder-blocks-clickable": "^4.0.6",
19
+ "@khanacademy/wonder-blocks-clickable": "^4.0.7",
20
20
  "@khanacademy/wonder-blocks-color": "^2.0.1",
21
21
  "@khanacademy/wonder-blocks-core": "^6.2.0",
22
22
  "@khanacademy/wonder-blocks-icon": "^2.1.6"