@khanacademy/wonder-blocks-card 0.0.0-PR2816-20251007223425 → 0.0.0-PR2817-20251007222151
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,10 +1,10 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-card
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-PR2817-20251007222151
|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Patch Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
7
|
+
- @khanacademy/wonder-blocks-icon-button@0.0.0-PR2817-20251007222151
|
|
8
8
|
|
|
9
9
|
## 1.1.0
|
|
10
10
|
|
package/dist/es/index.js
CHANGED
|
@@ -9,6 +9,6 @@ import { focusStyles } from '@khanacademy/wonder-blocks-styles';
|
|
|
9
9
|
|
|
10
10
|
const DismissButton=props=>{const{onClick,style,testId}=props;return jsx(IconButton,{icon:xIcon,"aria-label":props["aria-label"]||"Close",onClick:onClick,kind:"tertiary",actionType:"neutral",style:[componentStyles.root,style],testId:testId})};const componentStyles=StyleSheet.create({root:{position:"absolute",insetInlineEnd:sizing.size_080,top:sizing.size_080,zIndex:1,":focus":focusStyles.focus[":focus-visible"]}});
|
|
11
11
|
|
|
12
|
-
const Card=React.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxs(View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const styleMap={backgroundColor:{"base-subtle":semanticColor.core.background.base.subtle,"base-default":semanticColor.core.background.base.default},borderRadius:{small:border.radius.radius_080,medium:border.radius.radius_120},padding:{none:sizing.size_0,small:sizing.size_160,medium:sizing.size_240},elevation:{none:"none",low:boxShadow.low}};
|
|
12
|
+
const Card=React.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxs(View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const getComponentStyles=({background,borderRadius,paddingSize,elevation})=>{const styleMap={backgroundColor:{"base-subtle":semanticColor.core.background.base.subtle,"base-default":semanticColor.core.background.base.default},borderRadius:{small:border.radius.radius_080,medium:border.radius.radius_120},padding:{none:sizing.size_0,small:sizing.size_160,medium:sizing.size_240},elevation:{none:"none",low:boxShadow.low}};return StyleSheet.create({root:{backgroundColor:background&&styleMap.backgroundColor[background],borderColor:semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderRadius:borderRadius&&styleMap.borderRadius[borderRadius],borderWidth:border.width.thin,boxShadow:elevation&&styleMap.elevation[elevation],padding:paddingSize&&styleMap.padding[paddingSize],minInlineSize:sizing.size_280,position:"relative"}})};
|
|
13
13
|
|
|
14
14
|
export { Card };
|
package/dist/index.js
CHANGED
|
@@ -37,6 +37,6 @@ var IconButton__default = /*#__PURE__*/_interopDefaultLegacy(IconButton);
|
|
|
37
37
|
|
|
38
38
|
const DismissButton=props=>{const{onClick,style,testId}=props;return jsxRuntime.jsx(IconButton__default["default"],{icon:xIcon__default["default"],"aria-label":props["aria-label"]||"Close",onClick:onClick,kind:"tertiary",actionType:"neutral",style:[componentStyles.root,style],testId:testId})};const componentStyles=aphrodite.StyleSheet.create({root:{position:"absolute",insetInlineEnd:wonderBlocksTokens.sizing.size_080,top:wonderBlocksTokens.sizing.size_080,zIndex:1,":focus":wonderBlocksStyles.focusStyles.focus[":focus-visible"]}});
|
|
39
39
|
|
|
40
|
-
const Card=React__namespace.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxRuntime.jsxs(wonderBlocksCore.View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsxRuntime.jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const styleMap={backgroundColor:{"base-subtle":wonderBlocksTokens.semanticColor.core.background.base.subtle,"base-default":wonderBlocksTokens.semanticColor.core.background.base.default},borderRadius:{small:wonderBlocksTokens.border.radius.radius_080,medium:wonderBlocksTokens.border.radius.radius_120},padding:{none:wonderBlocksTokens.sizing.size_0,small:wonderBlocksTokens.sizing.size_160,medium:wonderBlocksTokens.sizing.size_240},elevation:{none:"none",low:wonderBlocksTokens.boxShadow.low}};
|
|
40
|
+
const Card=React__namespace.forwardRef(function Card(props,ref){const{styles,labels,tag,testId,background="base-default",borderRadius="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({background,borderRadius,paddingSize,elevation});return jsxRuntime.jsxs(wonderBlocksCore.View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,styles?.root],ref:ref,tag:tag,testId:testId,inert:inert?"":undefined,children:[onDismiss?jsxRuntime.jsx(DismissButton,{"aria-label":labels?.dismissButtonAriaLabel||"Close",onClick:e=>onDismiss?.(e)}):null,children]})});const getComponentStyles=({background,borderRadius,paddingSize,elevation})=>{const styleMap={backgroundColor:{"base-subtle":wonderBlocksTokens.semanticColor.core.background.base.subtle,"base-default":wonderBlocksTokens.semanticColor.core.background.base.default},borderRadius:{small:wonderBlocksTokens.border.radius.radius_080,medium:wonderBlocksTokens.border.radius.radius_120},padding:{none:wonderBlocksTokens.sizing.size_0,small:wonderBlocksTokens.sizing.size_160,medium:wonderBlocksTokens.sizing.size_240},elevation:{none:"none",low:wonderBlocksTokens.boxShadow.low}};return aphrodite.StyleSheet.create({root:{backgroundColor:background&&styleMap.backgroundColor[background],borderColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderRadius:borderRadius&&styleMap.borderRadius[borderRadius],borderWidth:wonderBlocksTokens.border.width.thin,boxShadow:elevation&&styleMap.elevation[elevation],padding:paddingSize&&styleMap.padding[paddingSize],minInlineSize:wonderBlocksTokens.sizing.size_280,position:"relative"}})};
|
|
41
41
|
|
|
42
42
|
exports.Card = Card;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-card",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-PR2817-20251007222151",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"description": "Card component for Wonder Blocks.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@khanacademy/wonder-blocks-core": "12.4.0",
|
|
17
|
-
"@khanacademy/wonder-blocks-
|
|
18
|
-
"@khanacademy/wonder-blocks-
|
|
17
|
+
"@khanacademy/wonder-blocks-icon-button": "0.0.0-PR2817-20251007222151",
|
|
18
|
+
"@khanacademy/wonder-blocks-tokens": "14.0.0"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"aphrodite": "^1.2.5",
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import {render, screen} from "@testing-library/react";
|
|
3
3
|
import {userEvent} from "@testing-library/user-event";
|
|
4
|
-
import {
|
|
5
|
-
boxShadow,
|
|
6
|
-
border,
|
|
7
|
-
semanticColor,
|
|
8
|
-
sizing,
|
|
9
|
-
} from "@khanacademy/wonder-blocks-tokens";
|
|
10
4
|
|
|
11
5
|
import Card from "../../components/card";
|
|
12
6
|
|
|
@@ -197,180 +191,4 @@ describe("Card", () => {
|
|
|
197
191
|
expect(secondChild).toBeInTheDocument();
|
|
198
192
|
});
|
|
199
193
|
});
|
|
200
|
-
|
|
201
|
-
describe("Style application", () => {
|
|
202
|
-
it("should apply default styles", () => {
|
|
203
|
-
// Arrange
|
|
204
|
-
const testId = "test-card";
|
|
205
|
-
|
|
206
|
-
// Act
|
|
207
|
-
render(<Card testId={testId}>Content</Card>);
|
|
208
|
-
const card = screen.getByTestId(testId);
|
|
209
|
-
|
|
210
|
-
// Assert
|
|
211
|
-
expect(card).toHaveStyle({
|
|
212
|
-
position: "relative",
|
|
213
|
-
borderStyle: "solid",
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
it("should apply base-subtle background", () => {
|
|
218
|
-
// Arrange
|
|
219
|
-
const testId = "test-card";
|
|
220
|
-
|
|
221
|
-
// Act
|
|
222
|
-
render(
|
|
223
|
-
<Card testId={testId} background="base-subtle">
|
|
224
|
-
Content
|
|
225
|
-
</Card>,
|
|
226
|
-
);
|
|
227
|
-
const card = screen.getByTestId(testId);
|
|
228
|
-
|
|
229
|
-
// Assert
|
|
230
|
-
expect(card).toHaveStyle({
|
|
231
|
-
backgroundColor: semanticColor.core.background.base.subtle,
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it("should apply medium border radius", () => {
|
|
236
|
-
// Arrange
|
|
237
|
-
const testId = "test-card";
|
|
238
|
-
|
|
239
|
-
// Act
|
|
240
|
-
render(
|
|
241
|
-
<Card testId={testId} borderRadius="medium">
|
|
242
|
-
Content
|
|
243
|
-
</Card>,
|
|
244
|
-
);
|
|
245
|
-
const card = screen.getByTestId(testId);
|
|
246
|
-
|
|
247
|
-
// Assert
|
|
248
|
-
expect(card).toHaveStyle({
|
|
249
|
-
borderRadius: border.radius.radius_120,
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it("should apply medium padding", () => {
|
|
254
|
-
// Arrange
|
|
255
|
-
const testId = "test-card";
|
|
256
|
-
|
|
257
|
-
// Act
|
|
258
|
-
render(
|
|
259
|
-
<Card testId={testId} paddingSize="medium">
|
|
260
|
-
Content
|
|
261
|
-
</Card>,
|
|
262
|
-
);
|
|
263
|
-
const card = screen.getByTestId(testId);
|
|
264
|
-
|
|
265
|
-
// Assert
|
|
266
|
-
expect(card).toHaveStyle({
|
|
267
|
-
padding: sizing.size_240,
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it("should apply low elevation", () => {
|
|
272
|
-
// Arrange
|
|
273
|
-
const testId = "test-card";
|
|
274
|
-
|
|
275
|
-
// Act
|
|
276
|
-
render(
|
|
277
|
-
<Card testId={testId} elevation="low">
|
|
278
|
-
Content
|
|
279
|
-
</Card>,
|
|
280
|
-
);
|
|
281
|
-
const card = screen.getByTestId(testId);
|
|
282
|
-
|
|
283
|
-
// Assert
|
|
284
|
-
expect(card).toHaveStyle({
|
|
285
|
-
boxShadow: boxShadow.low,
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it("should apply image background", () => {
|
|
290
|
-
// Arrange
|
|
291
|
-
const testId = "test-card";
|
|
292
|
-
const testImage = Image;
|
|
293
|
-
|
|
294
|
-
// Act
|
|
295
|
-
render(
|
|
296
|
-
<Card testId={testId} background={testImage}>
|
|
297
|
-
Content
|
|
298
|
-
</Card>,
|
|
299
|
-
);
|
|
300
|
-
const card = screen.getByTestId(testId);
|
|
301
|
-
|
|
302
|
-
// Assert
|
|
303
|
-
expect(card).toHaveStyle({
|
|
304
|
-
backgroundSize: "cover",
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
describe("Style application", () => {
|
|
310
|
-
it("should apply custom margin style", () => {
|
|
311
|
-
// Arrange
|
|
312
|
-
const testId = "test-card";
|
|
313
|
-
const customStyle = {marginTop: "10px"};
|
|
314
|
-
|
|
315
|
-
// Act
|
|
316
|
-
render(
|
|
317
|
-
<Card testId={testId} styles={{root: customStyle}}>
|
|
318
|
-
Content
|
|
319
|
-
</Card>,
|
|
320
|
-
);
|
|
321
|
-
|
|
322
|
-
// Assert
|
|
323
|
-
expect(screen.getByTestId(testId)).toHaveStyle(customStyle);
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it("should apply custom padding style", () => {
|
|
327
|
-
// Arrange
|
|
328
|
-
const testId = "test-card";
|
|
329
|
-
const customStyle = {padding: "20px"};
|
|
330
|
-
|
|
331
|
-
// Act
|
|
332
|
-
render(
|
|
333
|
-
<Card testId={testId} styles={{root: customStyle}}>
|
|
334
|
-
Content
|
|
335
|
-
</Card>,
|
|
336
|
-
);
|
|
337
|
-
|
|
338
|
-
// Assert
|
|
339
|
-
expect(screen.getByTestId(testId)).toHaveStyle(customStyle);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it("should apply custom background color", () => {
|
|
343
|
-
// Arrange
|
|
344
|
-
const testId = "test-card";
|
|
345
|
-
const customStyle = {backgroundColor: "rgb(255, 0, 0)"};
|
|
346
|
-
|
|
347
|
-
// Act
|
|
348
|
-
render(
|
|
349
|
-
<Card testId={testId} styles={{root: customStyle}}>
|
|
350
|
-
Content
|
|
351
|
-
</Card>,
|
|
352
|
-
);
|
|
353
|
-
|
|
354
|
-
// Assert
|
|
355
|
-
expect(screen.getByTestId(testId)).toHaveStyle(customStyle);
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
it("should maintain default styles with custom styles", () => {
|
|
359
|
-
// Arrange
|
|
360
|
-
const testId = "test-card";
|
|
361
|
-
const customStyle = {marginTop: "10px"};
|
|
362
|
-
|
|
363
|
-
// Act
|
|
364
|
-
render(
|
|
365
|
-
<Card testId={testId} styles={{root: customStyle}}>
|
|
366
|
-
Content
|
|
367
|
-
</Card>,
|
|
368
|
-
);
|
|
369
|
-
|
|
370
|
-
// Assert
|
|
371
|
-
const element = screen.getByTestId(testId);
|
|
372
|
-
expect(element).toHaveStyle(customStyle);
|
|
373
|
-
expect(element).toHaveStyle({position: "relative"}); // A default style
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
194
|
});
|
package/src/components/card.tsx
CHANGED
|
@@ -79,13 +79,10 @@ type StyleProps = {
|
|
|
79
79
|
* This can be one of:
|
|
80
80
|
* - `"base-subtle"` (color), `semanticColor.core.background.base.subtle`: a light gray background.
|
|
81
81
|
* - `"base-default"` (color), `semanticColor.core.background.base.default`: a white background.
|
|
82
|
-
* - `Image` (image), a URL string for a background image. Can be an imported image file or a URL string.
|
|
83
|
-
*
|
|
84
|
-
* For additional background styling such as repeat or size, use the `styles.root` prop to pass in custom styles.
|
|
85
82
|
*
|
|
86
83
|
* Default: `"base-default"`
|
|
87
84
|
*/
|
|
88
|
-
background?: "base-subtle" | "base-default"
|
|
85
|
+
background?: "base-subtle" | "base-default";
|
|
89
86
|
/**
|
|
90
87
|
* The border radius of the card, as a string identifier that matches a border.radius token.
|
|
91
88
|
* This can be one of:
|
|
@@ -144,7 +141,7 @@ type Props = BaseCardProps & TagProps & DismissProps;
|
|
|
144
141
|
*
|
|
145
142
|
* When the `onDismiss` prop is provided, a dismiss button will be rendered. In this case, the `labels.dismissButtonAriaLabel` prop is required to provide an accessible label for the dismiss button.
|
|
146
143
|
*
|
|
147
|
-
* See additional Accessibility docs.
|
|
144
|
+
* See additional [Accessibility docs](./?path=/docs/packages-card-card-accessibility--docs).
|
|
148
145
|
*/
|
|
149
146
|
|
|
150
147
|
const Card = React.forwardRef(function Card(
|
|
@@ -191,87 +188,46 @@ const Card = React.forwardRef(function Card(
|
|
|
191
188
|
);
|
|
192
189
|
});
|
|
193
190
|
|
|
194
|
-
|
|
195
|
-
const styleMap = {
|
|
196
|
-
backgroundColor: {
|
|
197
|
-
"base-subtle": semanticColor.core.background.base.subtle,
|
|
198
|
-
"base-default": semanticColor.core.background.base.default,
|
|
199
|
-
},
|
|
200
|
-
borderRadius: {
|
|
201
|
-
small: border.radius.radius_080,
|
|
202
|
-
medium: border.radius.radius_120,
|
|
203
|
-
},
|
|
204
|
-
padding: {
|
|
205
|
-
none: sizing.size_0,
|
|
206
|
-
small: sizing.size_160,
|
|
207
|
-
medium: sizing.size_240,
|
|
208
|
-
},
|
|
209
|
-
elevation: {
|
|
210
|
-
none: "none",
|
|
211
|
-
low: boxShadow.low,
|
|
212
|
-
},
|
|
213
|
-
} as const;
|
|
214
|
-
|
|
215
|
-
// Cache for dynamically generated styles
|
|
216
|
-
const dynamicStyles: Record<string, any> = {};
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Generates a unique key for caching styles based on prop combinations
|
|
220
|
-
*/
|
|
221
|
-
const getStyleKey = ({
|
|
191
|
+
const getComponentStyles = ({
|
|
222
192
|
background,
|
|
223
193
|
borderRadius,
|
|
224
194
|
paddingSize,
|
|
225
195
|
elevation,
|
|
226
|
-
}: StyleProps)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
196
|
+
}: StyleProps) => {
|
|
197
|
+
// Map prop values to tokens
|
|
198
|
+
const styleMap = {
|
|
199
|
+
backgroundColor: {
|
|
200
|
+
"base-subtle": semanticColor.core.background.base.subtle,
|
|
201
|
+
"base-default": semanticColor.core.background.base.default,
|
|
202
|
+
},
|
|
203
|
+
borderRadius: {
|
|
204
|
+
small: border.radius.radius_080,
|
|
205
|
+
medium: border.radius.radius_120,
|
|
206
|
+
},
|
|
207
|
+
padding: {
|
|
208
|
+
none: sizing.size_0,
|
|
209
|
+
small: sizing.size_160,
|
|
210
|
+
medium: sizing.size_240,
|
|
211
|
+
},
|
|
212
|
+
elevation: {
|
|
213
|
+
none: "none",
|
|
214
|
+
low: boxShadow.low,
|
|
215
|
+
},
|
|
216
|
+
} as const;
|
|
245
217
|
|
|
246
|
-
|
|
247
|
-
const newStyles = StyleSheet.create({
|
|
218
|
+
return StyleSheet.create({
|
|
248
219
|
root: {
|
|
249
|
-
|
|
250
|
-
...(isBackgroundColorStyle && {
|
|
251
|
-
backgroundColor: styleMap.backgroundColor[background],
|
|
252
|
-
}),
|
|
253
|
-
// Background image styles
|
|
254
|
-
...(!isBackgroundColorStyle &&
|
|
255
|
-
background && {
|
|
256
|
-
background: `url(${background})`,
|
|
257
|
-
backgroundSize: "cover",
|
|
258
|
-
}),
|
|
259
|
-
// Common styles
|
|
220
|
+
backgroundColor: background && styleMap.backgroundColor[background],
|
|
260
221
|
borderColor: semanticColor.core.border.neutral.subtle,
|
|
261
222
|
borderStyle: "solid",
|
|
262
|
-
borderWidth: border.width.thin,
|
|
263
|
-
minInlineSize: sizing.size_280,
|
|
264
|
-
position: "relative",
|
|
265
|
-
// Optional styles based on props
|
|
266
223
|
borderRadius: borderRadius && styleMap.borderRadius[borderRadius],
|
|
224
|
+
borderWidth: border.width.thin,
|
|
267
225
|
boxShadow: elevation && styleMap.elevation[elevation],
|
|
268
226
|
padding: paddingSize && styleMap.padding[paddingSize],
|
|
227
|
+
minInlineSize: sizing.size_280,
|
|
228
|
+
position: "relative",
|
|
269
229
|
},
|
|
270
230
|
});
|
|
271
|
-
|
|
272
|
-
// Cache the styles
|
|
273
|
-
dynamicStyles[styleKey] = newStyles;
|
|
274
|
-
return newStyles;
|
|
275
231
|
};
|
|
276
232
|
|
|
277
233
|
export default Card;
|