@khanacademy/wonder-blocks-card 0.0.0-PR2817-20251008173555 → 1.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 +6 -2
- package/dist/es/index.js +2 -2
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/src/__tests__/components/card.typestest.tsx +3 -0
- package/src/components/card.tsx +55 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
# @khanacademy/wonder-blocks-card
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 607595f: Adds support for image backgrounds via the background prop
|
|
4
8
|
|
|
5
9
|
### Patch Changes
|
|
6
10
|
|
|
7
|
-
- @khanacademy/wonder-blocks-icon-button@
|
|
11
|
+
- @khanacademy/wonder-blocks-icon-button@10.5.3
|
|
8
12
|
|
|
9
13
|
## 1.1.0
|
|
10
14
|
|
package/dist/es/index.js
CHANGED
|
@@ -2,13 +2,13 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { StyleSheet } from 'aphrodite';
|
|
4
4
|
import { View } from '@khanacademy/wonder-blocks-core';
|
|
5
|
-
import { sizing, semanticColor, border, boxShadow } from '@khanacademy/wonder-blocks-tokens';
|
|
5
|
+
import { sizing, semanticColor, border, boxShadow, font } from '@khanacademy/wonder-blocks-tokens';
|
|
6
6
|
import xIcon from '@phosphor-icons/core/bold/x-bold.svg';
|
|
7
7
|
import IconButton from '@khanacademy/wonder-blocks-icon-button';
|
|
8
8
|
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
|
|
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 isBackgroundToken=background==="base-default"||background==="base-subtle";const componentStyles=getComponentStyles({background:isBackgroundToken?background:null,borderRadius,paddingSize,elevation});return jsxs(View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,!isBackgroundToken&&{background:`url(${background})`,backgroundSize:"cover"},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}};const getComponentStyles=({background="base-default",borderRadius="small",paddingSize="small",elevation="none"})=>{const bgColor=background;return StyleSheet.create({root:{backgroundColor:bgColor&&styleMap.backgroundColor[bgColor],borderColor:semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderWidth:border.width.thin,fontFamily:font.family.sans,minInlineSize:sizing.size_280,position:"relative",borderRadius:styleMap.borderRadius[borderRadius],boxShadow:styleMap.elevation[elevation],padding:styleMap.padding[paddingSize]}})};
|
|
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
|
|
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 isBackgroundToken=background==="base-default"||background==="base-subtle";const componentStyles=getComponentStyles({background:isBackgroundToken?background:null,borderRadius,paddingSize,elevation});return jsxRuntime.jsxs(wonderBlocksCore.View,{"aria-label":labels?.cardAriaLabel,style:[componentStyles.root,!isBackgroundToken&&{background:`url(${background})`,backgroundSize:"cover"},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}};const getComponentStyles=({background="base-default",borderRadius="small",paddingSize="small",elevation="none"})=>{const bgColor=background;return aphrodite.StyleSheet.create({root:{backgroundColor:bgColor&&styleMap.backgroundColor[bgColor],borderColor:wonderBlocksTokens.semanticColor.core.border.neutral.subtle,borderStyle:"solid",borderWidth:wonderBlocksTokens.border.width.thin,fontFamily:wonderBlocksTokens.font.family.sans,minInlineSize:wonderBlocksTokens.sizing.size_280,position:"relative",borderRadius:styleMap.borderRadius[borderRadius],boxShadow:styleMap.elevation[elevation],padding:styleMap.padding[paddingSize]}})};
|
|
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": "
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"description": "Card component for Wonder Blocks.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@khanacademy/wonder-blocks-core": "12.4.0",
|
|
17
|
-
"@khanacademy/wonder-blocks-icon-button": "
|
|
17
|
+
"@khanacademy/wonder-blocks-icon-button": "10.5.3",
|
|
18
18
|
"@khanacademy/wonder-blocks-tokens": "14.0.0"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
package/src/components/card.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
border,
|
|
9
9
|
semanticColor,
|
|
10
10
|
sizing,
|
|
11
|
+
font,
|
|
11
12
|
} from "@khanacademy/wonder-blocks-tokens";
|
|
12
13
|
|
|
13
14
|
import {DismissButton} from "./dismiss-button";
|
|
@@ -79,10 +80,13 @@ type StyleProps = {
|
|
|
79
80
|
* This can be one of:
|
|
80
81
|
* - `"base-subtle"` (color), `semanticColor.core.background.base.subtle`: a light gray background.
|
|
81
82
|
* - `"base-default"` (color), `semanticColor.core.background.base.default`: a white background.
|
|
83
|
+
* - `Image` (image), a URL string for a background image. Can be an imported image file or a URL string.
|
|
84
|
+
*
|
|
85
|
+
* For additional background styling such as repeat or size, use the `styles.root` prop to pass in custom styles.
|
|
82
86
|
*
|
|
83
87
|
* Default: `"base-default"`
|
|
84
88
|
*/
|
|
85
|
-
background?: "base-subtle" | "base-default";
|
|
89
|
+
background?: "base-subtle" | "base-default" | typeof Image | null;
|
|
86
90
|
/**
|
|
87
91
|
* The border radius of the card, as a string identifier that matches a border.radius token.
|
|
88
92
|
* This can be one of:
|
|
@@ -141,7 +145,7 @@ type Props = BaseCardProps & TagProps & DismissProps;
|
|
|
141
145
|
*
|
|
142
146
|
* 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.
|
|
143
147
|
*
|
|
144
|
-
* See additional
|
|
148
|
+
* See additional Accessibility docs.
|
|
145
149
|
*/
|
|
146
150
|
|
|
147
151
|
const Card = React.forwardRef(function Card(
|
|
@@ -162,16 +166,26 @@ const Card = React.forwardRef(function Card(
|
|
|
162
166
|
inert,
|
|
163
167
|
} = props;
|
|
164
168
|
|
|
169
|
+
const isBackgroundToken =
|
|
170
|
+
background === "base-default" || background === "base-subtle";
|
|
165
171
|
const componentStyles = getComponentStyles({
|
|
166
|
-
background,
|
|
172
|
+
background: isBackgroundToken ? background : null,
|
|
167
173
|
borderRadius,
|
|
168
174
|
paddingSize,
|
|
169
175
|
elevation,
|
|
170
176
|
});
|
|
177
|
+
|
|
171
178
|
return (
|
|
172
179
|
<View
|
|
173
180
|
aria-label={labels?.cardAriaLabel}
|
|
174
|
-
style={[
|
|
181
|
+
style={[
|
|
182
|
+
componentStyles.root,
|
|
183
|
+
!isBackgroundToken && {
|
|
184
|
+
background: `url(${background})`,
|
|
185
|
+
backgroundSize: "cover",
|
|
186
|
+
},
|
|
187
|
+
styles?.root,
|
|
188
|
+
]}
|
|
175
189
|
ref={ref}
|
|
176
190
|
tag={tag}
|
|
177
191
|
testId={testId}
|
|
@@ -188,44 +202,52 @@ const Card = React.forwardRef(function Card(
|
|
|
188
202
|
);
|
|
189
203
|
});
|
|
190
204
|
|
|
205
|
+
// Map prop values to tokens
|
|
206
|
+
const styleMap = {
|
|
207
|
+
backgroundColor: {
|
|
208
|
+
"base-subtle": semanticColor.core.background.base.subtle,
|
|
209
|
+
"base-default": semanticColor.core.background.base.default,
|
|
210
|
+
},
|
|
211
|
+
borderRadius: {
|
|
212
|
+
small: border.radius.radius_080,
|
|
213
|
+
medium: border.radius.radius_120,
|
|
214
|
+
},
|
|
215
|
+
padding: {
|
|
216
|
+
none: sizing.size_0,
|
|
217
|
+
small: sizing.size_160,
|
|
218
|
+
medium: sizing.size_240,
|
|
219
|
+
},
|
|
220
|
+
elevation: {
|
|
221
|
+
none: "none",
|
|
222
|
+
low: boxShadow.low,
|
|
223
|
+
},
|
|
224
|
+
} as const;
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Gets the styles for the card based on its props
|
|
228
|
+
*/
|
|
191
229
|
const getComponentStyles = ({
|
|
192
|
-
background,
|
|
193
|
-
borderRadius,
|
|
194
|
-
paddingSize,
|
|
195
|
-
elevation,
|
|
230
|
+
background = "base-default",
|
|
231
|
+
borderRadius = "small",
|
|
232
|
+
paddingSize = "small",
|
|
233
|
+
elevation = "none",
|
|
196
234
|
}: StyleProps) => {
|
|
197
|
-
|
|
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;
|
|
217
|
-
|
|
235
|
+
const bgColor = background as keyof typeof styleMap.backgroundColor;
|
|
218
236
|
return StyleSheet.create({
|
|
219
237
|
root: {
|
|
220
|
-
backgroundColor:
|
|
238
|
+
backgroundColor: bgColor && styleMap.backgroundColor[bgColor],
|
|
239
|
+
// Common styles
|
|
221
240
|
borderColor: semanticColor.core.border.neutral.subtle,
|
|
222
241
|
borderStyle: "solid",
|
|
223
|
-
borderRadius: borderRadius && styleMap.borderRadius[borderRadius],
|
|
224
242
|
borderWidth: border.width.thin,
|
|
225
|
-
|
|
226
|
-
|
|
243
|
+
// Apply the system font to cards by default
|
|
244
|
+
fontFamily: font.family.sans,
|
|
227
245
|
minInlineSize: sizing.size_280,
|
|
228
246
|
position: "relative",
|
|
247
|
+
// Optional styles based on props
|
|
248
|
+
borderRadius: styleMap.borderRadius[borderRadius],
|
|
249
|
+
boxShadow: styleMap.elevation[elevation],
|
|
250
|
+
padding: styleMap.padding[paddingSize],
|
|
229
251
|
},
|
|
230
252
|
});
|
|
231
253
|
};
|