@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 +18 -0
- package/dist/es/index.js +10 -12
- package/dist/index.js +10 -12
- package/package.json +1 -1
- package/src/components/__docs__/compact-cell.argtypes.js +12 -1
- package/src/components/__docs__/detail-cell.stories.js +53 -0
- package/src/components/internal/__tests__/cell-core.test.js +14 -0
- package/src/components/internal/cell-core.js +5 -2
- package/src/components/internal/common.js +2 -7
- package/src/util/types.js +14 -0
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
@@ -27,7 +27,7 @@ export const AccessoryMappings = {
|
|
|
27
27
|
</View>
|
|
28
28
|
): React.Element<typeof View>),
|
|
29
29
|
withImage: ((
|
|
30
|
-
<img src="
|
|
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.
|
|
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.
|
|
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
|
|};
|