@khanacademy/wonder-blocks-card 0.0.0-PR2799-20250930173028 → 0.0.0-PR2799-20251001174203

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,7 +1,11 @@
1
1
  # @khanacademy/wonder-blocks-card
2
2
 
3
- ## 0.0.0-PR2799-20250930173028
3
+ ## 0.0.0-PR2799-20251001174203
4
4
 
5
5
  ### Minor Changes
6
6
 
7
7
  - 7506aef: Add new Card component
8
+
9
+ ### Patch Changes
10
+
11
+ - @khanacademy/wonder-blocks-core@12.4.0
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,backgroundColorStyle="base-default",borderRadiusStyle="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({backgroundColorStyle,borderRadiusStyle,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=({backgroundColorStyle,borderRadiusStyle,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:backgroundColorStyle&&styleMap.backgroundColor[backgroundColorStyle],borderColor:semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderRadius:borderRadiusStyle&&styleMap.borderRadius[borderRadiusStyle],borderWidth:border.width.thin,boxShadow:elevation&&styleMap.elevation[elevation],padding:paddingSize&&styleMap.padding[paddingSize],minInlineSize:sizing.size_280,position:"relative"}})};
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,backgroundColorStyle="base-default",borderRadiusStyle="small",paddingSize="small",elevation="none",children,onDismiss,inert}=props;const componentStyles=getComponentStyles({backgroundColorStyle,borderRadiusStyle,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=({backgroundColorStyle,borderRadiusStyle,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:backgroundColorStyle&&styleMap.backgroundColor[backgroundColorStyle],borderColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderRadius:borderRadiusStyle&&styleMap.borderRadius[borderRadiusStyle],borderWidth:wonderBlocksTokens.border.width.thin,boxShadow:elevation&&styleMap.elevation[elevation],padding:paddingSize&&styleMap.padding[paddingSize],minInlineSize:wonderBlocksTokens.sizing.size_280,position:"relative"}})};
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-PR2799-20250930173028",
3
+ "version": "0.0.0-PR2799-20251001174203",
4
4
  "design": "v1",
5
5
  "description": "Card component for Wonder Blocks.",
6
6
  "main": "dist/index.js",
@@ -0,0 +1,150 @@
1
+ import * as React from "react";
2
+
3
+ import Card from "../../components/card";
4
+
5
+ /**
6
+ * Basic Card usage
7
+ */
8
+
9
+ <Card>Hello, world!</Card>;
10
+
11
+ <Card>
12
+ <div>Some content</div>
13
+ </Card>;
14
+
15
+ /**
16
+ * Card with all style props
17
+ */
18
+
19
+ <Card
20
+ background="base-default"
21
+ borderRadius="small"
22
+ paddingSize="small"
23
+ elevation="none"
24
+ >
25
+ Content
26
+ </Card>;
27
+
28
+ <Card
29
+ background="base-subtle"
30
+ borderRadius="medium"
31
+ paddingSize="medium"
32
+ elevation="low"
33
+ >
34
+ Content
35
+ </Card>;
36
+
37
+ <Card paddingSize="none">Content</Card>;
38
+
39
+ // @ts-expect-error - invalid background value
40
+ <Card background="invalid-background">Content</Card>;
41
+
42
+ // @ts-expect-error - invalid borderRadius value
43
+ <Card borderRadius="invalid-radius">Content</Card>;
44
+
45
+ // @ts-expect-error - invalid paddingSize value
46
+ <Card paddingSize="invalid-padding">Content</Card>;
47
+
48
+ // @ts-expect-error - invalid elevation value
49
+ <Card elevation="invalid-elevation">Content</Card>;
50
+
51
+ /**
52
+ * Card with dismiss functionality
53
+ */
54
+
55
+ <Card onDismiss={() => {}} labels={{dismissButtonAriaLabel: "Close card"}}>
56
+ Content
57
+ </Card>;
58
+
59
+ // @ts-expect-error - onDismiss requires dismissButtonAriaLabel
60
+ <Card onDismiss={() => {}}>Content</Card>;
61
+
62
+ // @ts-expect-error - onDismiss requires dismissButtonAriaLabel
63
+ <Card onDismiss={() => {}} labels={{}}>
64
+ Content
65
+ </Card>;
66
+
67
+ /**
68
+ * Card with different HTML tags
69
+ */
70
+
71
+ <Card tag="div">Content</Card>;
72
+
73
+ <Card tag="section" labels={{cardAriaLabel: "Card section"}}>
74
+ Content
75
+ </Card>;
76
+
77
+ <Card tag="figure" labels={{cardAriaLabel: "Card figure"}}>
78
+ Content
79
+ </Card>;
80
+
81
+ // @ts-expect-error - section tag requires cardAriaLabel
82
+ <Card tag="section">Content</Card>;
83
+
84
+ // @ts-expect-error - figure tag requires cardAriaLabel
85
+ <Card tag="figure">Content</Card>;
86
+
87
+ // @ts-expect-error - section tag requires cardAriaLabel in labels
88
+ <Card tag="section" labels={{}}>
89
+ Content
90
+ </Card>;
91
+
92
+ // @ts-expect-error - figure tag requires cardAriaLabel in labels
93
+ <Card tag="figure" labels={{}}>
94
+ Content
95
+ </Card>;
96
+
97
+ /**
98
+ * Card with additional props
99
+ */
100
+
101
+ <Card testId="my-card">Content</Card>;
102
+
103
+ <Card inert>Content</Card>;
104
+
105
+ <Card ref={React.createRef<HTMLDivElement>()}>Content</Card>;
106
+
107
+ <Card styles={{root: {width: 200}, dismissButton: {position: "absolute"}}}>
108
+ Content
109
+ </Card>;
110
+
111
+ /**
112
+ * Card with dismiss and section tag (complex case)
113
+ */
114
+
115
+ <Card
116
+ tag="section"
117
+ onDismiss={() => {}}
118
+ labels={{
119
+ cardAriaLabel: "Card section",
120
+ dismissButtonAriaLabel: "Close card",
121
+ }}
122
+ >
123
+ Content
124
+ </Card>;
125
+
126
+ /**
127
+ * Card with all props
128
+ */
129
+
130
+ <Card
131
+ background="base-subtle"
132
+ borderRadius="medium"
133
+ paddingSize="medium"
134
+ elevation="low"
135
+ tag="figure"
136
+ onDismiss={() => {}}
137
+ labels={{
138
+ cardAriaLabel: "Card figure",
139
+ dismissButtonAriaLabel: "Close card",
140
+ }}
141
+ testId="complex-card"
142
+ inert
143
+ styles={{
144
+ root: {width: 300},
145
+ dismissButton: {top: 10, right: 10},
146
+ }}
147
+ ref={React.createRef<HTMLElement>()}
148
+ >
149
+ <div>Complex content</div>
150
+ </Card>;
@@ -40,7 +40,7 @@ type BaseCardProps = {
40
40
  * The test ID used to locate this component in automated tests.
41
41
  */
42
42
  testId?: string;
43
- } & StyleOnlyProps;
43
+ } & StyleProps;
44
44
 
45
45
  /**
46
46
  * A callback function to handle dismissing the card. When this prop is present,
@@ -73,21 +73,16 @@ type TagProps =
73
73
  labels?: Record<string, any>;
74
74
  };
75
75
 
76
- /**
77
- * Combined props - these two requirements work independently
78
- */
79
- type ConditionalProps = BaseCardProps & TagProps & DismissProps;
80
-
81
- type StyleOnlyProps = {
76
+ type StyleProps = {
82
77
  /**
83
- * The background color of the card, as a string identifier that matches a semanticColor token.
78
+ * The background style of the card, as a string identifier that matches a semanticColor token.
84
79
  * This can be one of:
85
- * - `"base-subtle"` `semanticColor.core.background.base.subtle`: a light gray background.
86
- * - `"base-default"`, matching `semanticColor.core.background.base.default`: a white background.
80
+ * - `"base-subtle"` (color), `semanticColor.core.background.base.subtle`: a light gray background.
81
+ * - `"base-default"` (color), `semanticColor.core.background.base.default`: a white background.
87
82
  *
88
83
  * Default: `"base-default"`
89
84
  */
90
- backgroundColorStyle?: "base-subtle" | "base-default";
85
+ background?: "base-subtle" | "base-default";
91
86
  /**
92
87
  * The border radius of the card, as a string identifier that matches a border.radius token.
93
88
  * This can be one of:
@@ -96,7 +91,7 @@ type StyleOnlyProps = {
96
91
  *
97
92
  * Default: `"radius_080"`
98
93
  */
99
- borderRadiusStyle?: "small" | "medium";
94
+ borderRadius?: "small" | "medium";
100
95
  /**
101
96
  * The padding inside the card, as a string identifier that matches a sizing token.
102
97
  * This can be one of:
@@ -117,8 +112,8 @@ type StyleOnlyProps = {
117
112
  */
118
113
  elevation?: "none" | "low";
119
114
  };
120
- type Props = ConditionalProps;
121
115
 
116
+ type Props = BaseCardProps & TagProps & DismissProps;
122
117
  /**
123
118
  * The Card component is a flexible, reusable UI building block designed to
124
119
  * encapsulate content within a structured, visually distinct container.
@@ -148,14 +143,14 @@ type Props = ConditionalProps;
148
143
  *
149
144
  * Cards can be customized via the following props:
150
145
  *
151
- * **`backgroundColorStyle` prop**
146
+ * **`background` prop**
152
147
  *
153
148
  * | value | resolves to |
154
149
  * |---|---|
155
150
  * | `base-subtle` | `semanticColor.core.background.base.subtle` (light gray) |
156
151
  * | `base-default` | `semanticColor.core.background.base.default` (white) |
157
152
  *
158
- * **`borderRadiusStyle` prop**
153
+ * **`borderRadius` prop**
159
154
  *
160
155
  * | value | resolves to |
161
156
  * |---|---|
@@ -194,8 +189,8 @@ const Card = React.forwardRef(function Card(
194
189
  labels,
195
190
  tag,
196
191
  testId,
197
- backgroundColorStyle = "base-default",
198
- borderRadiusStyle = "small",
192
+ background = "base-default",
193
+ borderRadius = "small",
199
194
  paddingSize = "small",
200
195
  elevation = "none",
201
196
  children,
@@ -204,8 +199,8 @@ const Card = React.forwardRef(function Card(
204
199
  } = props;
205
200
 
206
201
  const componentStyles = getComponentStyles({
207
- backgroundColorStyle,
208
- borderRadiusStyle,
202
+ background,
203
+ borderRadius,
209
204
  paddingSize,
210
205
  elevation,
211
206
  });
@@ -230,11 +225,11 @@ const Card = React.forwardRef(function Card(
230
225
  });
231
226
 
232
227
  const getComponentStyles = ({
233
- backgroundColorStyle,
234
- borderRadiusStyle,
228
+ background,
229
+ borderRadius,
235
230
  paddingSize,
236
231
  elevation,
237
- }: StyleOnlyProps) => {
232
+ }: StyleProps) => {
238
233
  // Map prop values to tokens
239
234
  const styleMap = {
240
235
  backgroundColor: {
@@ -258,13 +253,10 @@ const getComponentStyles = ({
258
253
 
259
254
  return StyleSheet.create({
260
255
  root: {
261
- backgroundColor:
262
- backgroundColorStyle &&
263
- styleMap.backgroundColor[backgroundColorStyle],
256
+ backgroundColor: background && styleMap.backgroundColor[background],
264
257
  borderColor: semanticColor.core.border.neutral.subtle,
265
258
  borderStyle: "solid",
266
- borderRadius:
267
- borderRadiusStyle && styleMap.borderRadius[borderRadiusStyle],
259
+ borderRadius: borderRadius && styleMap.borderRadius[borderRadius],
268
260
  borderWidth: border.width.thin,
269
261
  boxShadow: elevation && styleMap.elevation[elevation],
270
262
  padding: paddingSize && styleMap.padding[paddingSize],