@khanacademy/wonder-blocks-cell 2.0.2 → 2.2.1

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,23 @@
1
1
  # @khanacademy/wonder-blocks-cell
2
2
 
3
+ ## 2.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - eadd9c0d: Fix top vertical alignment between accessories and content
8
+
9
+ ## 2.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 35b9ef9c: Add target prop to cell.
14
+
15
+ ## 2.1.0
16
+
17
+ ### Minor Changes
18
+
19
+ - 9819c13f: Add href prop for client-side navigation
20
+
3
21
  ## 2.0.2
4
22
 
5
23
  ### Patch Changes
package/dist/es/index.js CHANGED
@@ -16,7 +16,7 @@ const CellMeasurements = {
16
16
  * The cell wrapper's gap.
17
17
  */
18
18
  cellPadding: {
19
- paddingVertical: Spacing.xSmall_8,
19
+ paddingVertical: Spacing.small_12,
20
20
  paddingHorizontal: Spacing.medium_16
21
21
  },
22
22
 
@@ -24,15 +24,10 @@ const CellMeasurements = {
24
24
  * The DetailCell wrapper's gap.
25
25
  */
26
26
  detailCellPadding: {
27
- paddingVertical: Spacing.small_12,
27
+ paddingVertical: Spacing.medium_16,
28
28
  paddingHorizontal: Spacing.medium_16
29
29
  },
30
30
 
31
- /**
32
- * The extra vertical spacing added to the title/content wrapper.
33
- */
34
- contentVerticalSpacing: Spacing.xxxSmall_4,
35
-
36
31
  /**
37
32
  * The horizontal spacing between the left and right accessory.
38
33
  */
@@ -134,6 +129,7 @@ const CellCore = props => {
134
129
  active,
135
130
  children,
136
131
  disabled,
132
+ href,
137
133
  horizontalRule = "inset",
138
134
  leftAccessory = undefined,
139
135
  leftAccessoryStyle = undefined,
@@ -143,7 +139,8 @@ const CellCore = props => {
143
139
  style,
144
140
  testId,
145
141
  "aria-label": ariaLabel,
146
- innerStyle
142
+ innerStyle,
143
+ target
147
144
  } = props;
148
145
 
149
146
  const renderCell = eventState => {
@@ -176,12 +173,14 @@ const CellCore = props => {
176
173
  }; // Pressable cell.
177
174
 
178
175
 
179
- if (onClick) {
176
+ if (onClick || href) {
180
177
  return /*#__PURE__*/React.createElement(Clickable, {
181
178
  disabled: disabled,
182
179
  onClick: onClick,
180
+ href: href,
183
181
  hideDefaultFocusRing: true,
184
- "aria-label": ariaLabel ? ariaLabel : undefined
182
+ "aria-label": ariaLabel ? ariaLabel : undefined,
183
+ target: target
185
184
  }, eventState => renderCell(eventState));
186
185
  } // No click event attached, so just render the cell as-is.
187
186
 
@@ -203,8 +202,7 @@ const styles$1 = StyleSheet.create({
203
202
  },
204
203
  content: {
205
204
  alignSelf: "center",
206
- overflowWrap: "break-word",
207
- padding: `${CellMeasurements.contentVerticalSpacing}px 0`
205
+ overflowWrap: "break-word"
208
206
  },
209
207
  accessory: {
210
208
  // Use content width by default.
package/dist/index.js CHANGED
@@ -126,7 +126,7 @@ const CellMeasurements = {
126
126
  * The cell wrapper's gap.
127
127
  */
128
128
  cellPadding: {
129
- paddingVertical: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_2___default.a.xSmall_8,
129
+ paddingVertical: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_2___default.a.small_12,
130
130
  paddingHorizontal: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_2___default.a.medium_16
131
131
  },
132
132
 
@@ -134,15 +134,10 @@ const CellMeasurements = {
134
134
  * The DetailCell wrapper's gap.
135
135
  */
136
136
  detailCellPadding: {
137
- paddingVertical: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_2___default.a.small_12,
137
+ paddingVertical: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_2___default.a.medium_16,
138
138
  paddingHorizontal: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_2___default.a.medium_16
139
139
  },
140
140
 
141
- /**
142
- * The extra vertical spacing added to the title/content wrapper.
143
- */
144
- contentVerticalSpacing: _khanacademy_wonder_blocks_spacing__WEBPACK_IMPORTED_MODULE_2___default.a.xxxSmall_4,
145
-
146
141
  /**
147
142
  * The horizontal spacing between the left and right accessory.
148
143
  */
@@ -299,6 +294,7 @@ const CellCore = props => {
299
294
  active,
300
295
  children,
301
296
  disabled,
297
+ href,
302
298
  horizontalRule = "inset",
303
299
  leftAccessory = undefined,
304
300
  leftAccessoryStyle = undefined,
@@ -308,7 +304,8 @@ const CellCore = props => {
308
304
  style,
309
305
  testId,
310
306
  "aria-label": ariaLabel,
311
- innerStyle
307
+ innerStyle,
308
+ target
312
309
  } = props;
313
310
 
314
311
  const renderCell = eventState => {
@@ -341,12 +338,14 @@ const CellCore = props => {
341
338
  }; // Pressable cell.
342
339
 
343
340
 
344
- if (onClick) {
341
+ if (onClick || href) {
345
342
  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0__["createElement"](_khanacademy_wonder_blocks_clickable__WEBPACK_IMPORTED_MODULE_2___default.a, {
346
343
  disabled: disabled,
347
344
  onClick: onClick,
345
+ href: href,
348
346
  hideDefaultFocusRing: true,
349
- "aria-label": ariaLabel ? ariaLabel : undefined
347
+ "aria-label": ariaLabel ? ariaLabel : undefined,
348
+ target: target
350
349
  }, eventState => renderCell(eventState));
351
350
  } // No click event attached, so just render the cell as-is.
352
351
 
@@ -368,8 +367,7 @@ const styles = aphrodite__WEBPACK_IMPORTED_MODULE_1__["StyleSheet"].create({
368
367
  },
369
368
  content: {
370
369
  alignSelf: "center",
371
- overflowWrap: "break-word",
372
- padding: `${_common_js__WEBPACK_IMPORTED_MODULE_7__[/* CellMeasurements */ "a"].contentVerticalSpacing}px 0`
370
+ overflowWrap: "break-word"
373
371
  },
374
372
  accessory: {
375
373
  // Use content width by default.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-cell",
3
- "version": "2.0.2",
3
+ "version": "2.2.1",
4
4
  "design": "v1",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -27,7 +27,7 @@ export const AccessoryMappings = {
27
27
  </View>
28
28
  ): React.Element<typeof View>),
29
29
  withImage: ((
30
- <img src="/avatar.png" alt="ItemAvatar" width={48} height={48} />
30
+ <img src="./avatar.png" alt="ItemAvatar" width={48} height={48} />
31
31
  ): React$Element<"img">),
32
32
  };
33
33
 
@@ -121,6 +121,17 @@ export default {
121
121
  },
122
122
  },
123
123
  },
124
+ href: {
125
+ description:
126
+ "Optional href which Cell should direct to, uses client-side routing by default if react-router is present.",
127
+ control: {type: "text"},
128
+ table: {
129
+ category: "Navigation",
130
+ type: {
131
+ summary: "string",
132
+ },
133
+ },
134
+ },
124
135
  onClick: {
125
136
  action: "clicked",
126
137
  description: `Called when the cell is clicked.
@@ -1,6 +1,7 @@
1
1
  // @flow
2
2
  import * as React from "react";
3
3
  import {StyleSheet} from "aphrodite";
4
+ import {MemoryRouter, Route, Switch} from "react-router-dom";
4
5
 
5
6
  import {View} from "@khanacademy/wonder-blocks-core";
6
7
  import Color from "@khanacademy/wonder-blocks-color";
@@ -109,6 +110,7 @@ export const DetailCellWithCustomStyles: StoryComponentType = () => (
109
110
  leftAccessory={<Icon icon={icons.contentVideo} size="medium" />}
110
111
  leftAccessoryStyle={{
111
112
  minWidth: Spacing.xxLarge_48,
113
+ alignSelf: "flex-start",
112
114
  }}
113
115
  rightAccessory={<Icon icon={icons.caretRight} size="small" />}
114
116
  rightAccessoryStyle={{
@@ -145,10 +147,61 @@ ClickableDetailCell.parameters = {
145
147
  },
146
148
  };
147
149
 
150
+ export const DetailCellNavigation: StoryComponentType = () => (
151
+ <MemoryRouter>
152
+ <View>
153
+ <DetailCell
154
+ title="Data"
155
+ subtitle2="Subtitle for article item"
156
+ leftAccessory={<Icon icon={icons.contentVideo} size="medium" />}
157
+ rightAccessory={<Icon icon={icons.caretRight} />}
158
+ href="/math/algebra"
159
+ aria-label="Press to navigate to the article"
160
+ />
161
+ <DetailCell
162
+ title="Geometry"
163
+ subtitle2="Subtitle for article item"
164
+ leftAccessory={<Icon icon={icons.contentVideo} size="medium" />}
165
+ rightAccessory={<Icon icon={icons.caretRight} />}
166
+ href="/math/geometry"
167
+ aria-label="Press to navigate to the article"
168
+ horizontalRule="none"
169
+ />
170
+ </View>
171
+
172
+ <View style={styles.navigation}>
173
+ <Switch>
174
+ <Route path="/math/algebra">Navigates to /math/algebra</Route>
175
+ <Route path="/math/geometry">Navigates to /math/geometry</Route>
176
+ <Route path="*">See navigation changes here</Route>
177
+ </Switch>
178
+ </View>
179
+ </MemoryRouter>
180
+ );
181
+
182
+ DetailCellNavigation.storyName = "Client-side navigation with DetailCell";
183
+
184
+ DetailCellNavigation.parameters = {
185
+ chromatic: {
186
+ // This only includes interactions with the clickable cell, so no need
187
+ // to capture screenshots.
188
+ disableSnapshot: true,
189
+ },
190
+ docs: {
191
+ storyDescription:
192
+ "Cells accept an `href` prop to be able to navigate to a different URL. Note that this will use client-side navigation if the Cell component is within a React-Router environment.",
193
+ },
194
+ };
195
+
148
196
  const styles = StyleSheet.create({
149
197
  example: {
150
198
  backgroundColor: Color.offWhite,
151
199
  padding: Spacing.large_24,
152
200
  width: 376,
153
201
  },
202
+ navigation: {
203
+ border: `1px dashed ${Color.lightBlue}`,
204
+ marginTop: Spacing.large_24,
205
+ padding: Spacing.large_24,
206
+ },
154
207
  });
@@ -47,6 +47,20 @@ describe("CellCore", () => {
47
47
  expect(screen.getByRole("button")).toBeInTheDocument();
48
48
  });
49
49
 
50
+ it("should add an anchor if href is set", () => {
51
+ // Arrange
52
+
53
+ // Act
54
+ render(
55
+ <CellCore href="/math">
56
+ <div>cell core content</div>
57
+ </CellCore>,
58
+ );
59
+
60
+ // Assert
61
+ expect(screen.getByRole("link")).toHaveAttribute("href", "/math");
62
+ });
63
+
50
64
  it("should add aria-label to the button", () => {
51
65
  // Arrange
52
66
 
@@ -119,6 +119,7 @@ const CellCore = (props: CellCoreProps): React.Node => {
119
119
  active,
120
120
  children,
121
121
  disabled,
122
+ href,
122
123
  horizontalRule = "inset",
123
124
  leftAccessory = undefined,
124
125
  leftAccessoryStyle = undefined,
@@ -129,6 +130,7 @@ const CellCore = (props: CellCoreProps): React.Node => {
129
130
  testId,
130
131
  "aria-label": ariaLabel,
131
132
  innerStyle,
133
+ target,
132
134
  } = props;
133
135
 
134
136
  const renderCell = (eventState?: ClickableState): React.Node => {
@@ -191,13 +193,15 @@ const CellCore = (props: CellCoreProps): React.Node => {
191
193
  };
192
194
 
193
195
  // Pressable cell.
194
- if (onClick) {
196
+ if (onClick || href) {
195
197
  return (
196
198
  <Clickable
197
199
  disabled={disabled}
198
200
  onClick={onClick}
201
+ href={href}
199
202
  hideDefaultFocusRing={true}
200
203
  aria-label={ariaLabel ? ariaLabel : undefined}
204
+ target={target}
201
205
  >
202
206
  {(eventState) => renderCell(eventState)}
203
207
  </Clickable>
@@ -225,7 +229,6 @@ const styles = StyleSheet.create({
225
229
  content: {
226
230
  alignSelf: "center",
227
231
  overflowWrap: "break-word",
228
- padding: `${CellMeasurements.contentVerticalSpacing}px 0`,
229
232
  },
230
233
 
231
234
  accessory: {
@@ -14,7 +14,7 @@ export const CellMeasurements = {
14
14
  * The cell wrapper's gap.
15
15
  */
16
16
  cellPadding: {
17
- paddingVertical: Spacing.xSmall_8,
17
+ paddingVertical: Spacing.small_12,
18
18
  paddingHorizontal: Spacing.medium_16,
19
19
  },
20
20
 
@@ -22,15 +22,10 @@ export const CellMeasurements = {
22
22
  * The DetailCell wrapper's gap.
23
23
  */
24
24
  detailCellPadding: {
25
- paddingVertical: Spacing.small_12,
25
+ paddingVertical: Spacing.medium_16,
26
26
  paddingHorizontal: Spacing.medium_16,
27
27
  },
28
28
 
29
- /**
30
- * The extra vertical spacing added to the title/content wrapper.
31
- */
32
- contentVerticalSpacing: Spacing.xxxSmall_4,
33
-
34
29
  /**
35
30
  * The horizontal spacing between the left and right accessory.
36
31
  */
package/src/util/types.js CHANGED
@@ -126,4 +126,18 @@ export type CellProps = {|
126
126
  * Used to announce the cell's content to screen readers.
127
127
  */
128
128
  "aria-label"?: string,
129
+
130
+ /**
131
+ * Optinal href which Cell should direct to, uses client-side routing
132
+ * by default if react-router is present.
133
+ */
134
+ href?: string,
135
+
136
+ /**
137
+ * A target destination window for a link to open in. Should only be used
138
+ * when `href` is specified.
139
+ *
140
+ * TODO(WB-1262): only allow this prop when `href` is also set.t
141
+ */
142
+ target?: "_blank",
129
143
  |};