@telus-uds/components-web 4.18.0 → 4.18.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 -6
- package/lib/cjs/Card/Card.js +40 -23
- package/lib/cjs/Card/CardContent.js +36 -7
- package/lib/cjs/Testimonial/Testimonial.js +2 -1
- package/lib/esm/Card/Card.js +40 -23
- package/lib/esm/Card/CardContent.js +36 -7
- package/lib/esm/Testimonial/Testimonial.js +1 -0
- package/package.json +3 -3
- package/src/Card/Card.jsx +49 -18
- package/src/Card/CardContent.jsx +40 -8
- package/src/Testimonial/Testimonial.jsx +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,28 +1,40 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-web
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Wed, 18 Feb 2026 02:50:19 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 4.18.1
|
|
8
|
+
|
|
9
|
+
Wed, 18 Feb 2026 02:50:19 GMT
|
|
10
|
+
|
|
11
|
+
### Patches
|
|
12
|
+
|
|
13
|
+
- refactor: simplify cardBaseTokens object creation by removing redundant destructuring (josue.higueroscalderon@telus.com)
|
|
14
|
+
- `IconButton`: Update stories (david.melara1@telus.com)
|
|
15
|
+
- `Card`: background image hidden behind the default color issue fixed (josue.higueroscalderon@telus.com)
|
|
16
|
+
- Bump @telus-uds/components-base to v3.28.0
|
|
17
|
+
- Bump @telus-uds/system-theme-tokens to v4.20.0
|
|
18
|
+
|
|
7
19
|
## 4.18.0
|
|
8
20
|
|
|
9
|
-
Thu, 29 Jan 2026
|
|
21
|
+
Thu, 29 Jan 2026 15:50:17 GMT
|
|
10
22
|
|
|
11
23
|
### Minor changes
|
|
12
24
|
|
|
13
|
-
- `NavigationBar`: add contentMaxWidth prop (guillermo.peitzner@telus.com)
|
|
14
25
|
- `List`: new feature alignment for the icons added (josue.higueroscalderon@telus.com)
|
|
15
|
-
- `QuantitySelector`: add inactive prop (guillermo.peitzner@telus.com)
|
|
16
26
|
- `Card`: Add full-bleed content support to Card component allowing content to extend to card edges (josue.higueroscalderon@telus.com)
|
|
27
|
+
- `QuantitySelector`: add inactive prop (guillermo.peitzner@telus.com)
|
|
17
28
|
- `Card`: Unnecessary comments removed. (josue.higueroscalderon@telus.com)
|
|
29
|
+
- `NavigationBar`: add contentMaxWidth prop (guillermo.peitzner@telus.com)
|
|
18
30
|
- Bump @telus-uds/components-base to v3.27.0
|
|
19
31
|
- Bump @telus-uds/system-theme-tokens to v4.19.0
|
|
20
32
|
|
|
21
33
|
### Patches
|
|
22
34
|
|
|
23
|
-
- `Card`: component enhaced to manage the hover, focus and pressed states of interactiveCard properly (josue.higueroscalderon@telus.com)
|
|
24
|
-
- `NavigationBar`: fix console warning (guillermo.peitzner@telus.com)
|
|
25
35
|
- `QuantitySelector`: spacer alignment issue fixed (josue.higueroscalderon@telus.com)
|
|
36
|
+
- `NavigationBar`: fix console warning (guillermo.peitzner@telus.com)
|
|
37
|
+
- `Card`: component enhaced to manage the hover, focus and pressed states of interactiveCard properly (josue.higueroscalderon@telus.com)
|
|
26
38
|
|
|
27
39
|
## 4.17.0
|
|
28
40
|
|
package/lib/cjs/Card/Card.js
CHANGED
|
@@ -58,11 +58,9 @@ const getCardContentTokens = function (baseTokens) {
|
|
|
58
58
|
// Determine background color based on conditions
|
|
59
59
|
let backgroundColorOverride = {};
|
|
60
60
|
if (useTransparentBackground) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
};
|
|
65
|
-
}
|
|
61
|
+
backgroundColorOverride = {
|
|
62
|
+
backgroundColor: 'transparent'
|
|
63
|
+
};
|
|
66
64
|
} else if (backgroundImage) {
|
|
67
65
|
backgroundColorOverride = {
|
|
68
66
|
backgroundColor: 'transparent'
|
|
@@ -236,7 +234,11 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
236
234
|
|
|
237
235
|
// If the card has rounded corners and a full bleed image, we need to apply
|
|
238
236
|
// those corners on the image as well, but partially
|
|
239
|
-
const
|
|
237
|
+
const variantForTokens = backgroundImage ? {
|
|
238
|
+
...variant,
|
|
239
|
+
style: undefined
|
|
240
|
+
} : variant;
|
|
241
|
+
const allThemeTokens = (0, _componentsBase.useThemeTokens)('Card', tokens, variantForTokens);
|
|
240
242
|
const {
|
|
241
243
|
borderRadius
|
|
242
244
|
} = allThemeTokens;
|
|
@@ -289,16 +291,17 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
289
291
|
interactive: true
|
|
290
292
|
});
|
|
291
293
|
|
|
292
|
-
//
|
|
293
|
-
|
|
294
|
-
const {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
294
|
+
// Keep backgroundColor for CardContent, it won't affect FullBleedContent image
|
|
295
|
+
const tokensWithoutBg = tokens;
|
|
296
|
+
const fullBleedInteractiveVariant = backgroundImage ? {
|
|
297
|
+
...variant,
|
|
298
|
+
interactive: true,
|
|
299
|
+
style: undefined
|
|
300
|
+
} : {
|
|
299
301
|
...variant,
|
|
300
302
|
interactive: true
|
|
301
|
-
}
|
|
303
|
+
};
|
|
304
|
+
const getFullBleedInteractiveTokens = (0, _componentsBase.useThemeTokensCallback)('Card', tokensWithoutBg, fullBleedInteractiveVariant);
|
|
302
305
|
const getFullBleedInteractiveCardTokens = cardState => {
|
|
303
306
|
return {
|
|
304
307
|
...getFullBleedInteractiveTokens(cardState),
|
|
@@ -342,8 +345,16 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
342
345
|
};
|
|
343
346
|
const cardBaseTokens = Object.fromEntries(Object.entries(tokens).filter(_ref4 => {
|
|
344
347
|
let [key] = _ref4;
|
|
345
|
-
return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage
|
|
348
|
+
return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage ? ['backgroundColor', 'gradient', 'backgroundGradient'] : [])].includes(key);
|
|
346
349
|
}));
|
|
350
|
+
const cardBaseVariant = backgroundImage ? {
|
|
351
|
+
...(interactiveCard?.body ? mergedVariant : variant),
|
|
352
|
+
padding: 'custom',
|
|
353
|
+
style: undefined
|
|
354
|
+
} : {
|
|
355
|
+
...(interactiveCard?.body ? mergedVariant : variant),
|
|
356
|
+
padding: 'custom'
|
|
357
|
+
};
|
|
347
358
|
const isHorizontalFullBleed = fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT;
|
|
348
359
|
const isVerticalFullBleed = fullBleedContentPosition === POSITION.TOP || fullBleedContentPosition === POSITION.BOTTOM;
|
|
349
360
|
const imageWrapperStyleProps = {
|
|
@@ -360,12 +371,9 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
360
371
|
};
|
|
361
372
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.Card, {
|
|
362
373
|
ref: ref,
|
|
363
|
-
variant:
|
|
364
|
-
...(interactiveCard?.body ? mergedVariant : variant),
|
|
365
|
-
padding: 'custom'
|
|
366
|
-
},
|
|
374
|
+
variant: cardBaseVariant,
|
|
367
375
|
tokens: cardBaseTokens,
|
|
368
|
-
backgroundImage:
|
|
376
|
+
backgroundImage: backgroundImage,
|
|
369
377
|
onPress: fullBleedInteractive ? undefined : onPress,
|
|
370
378
|
...(interactiveCard?.selectionType && {
|
|
371
379
|
interactiveCard,
|
|
@@ -373,16 +381,18 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
373
381
|
}),
|
|
374
382
|
...selectProps(restProps),
|
|
375
383
|
children: [interactiveCard?.selectionType && children ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
|
|
376
|
-
tokens: tokens,
|
|
384
|
+
tokens: getCardContentTokens(tokens, {
|
|
385
|
+
backgroundImage
|
|
386
|
+
}),
|
|
377
387
|
variant: variant,
|
|
378
388
|
withFooter: hasFooter,
|
|
389
|
+
backgroundImage: backgroundImage,
|
|
379
390
|
children: children
|
|
380
391
|
}) : null, interactiveCard?.body && !interactiveCard.selectionType ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
381
392
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.PressableCardBase, {
|
|
382
393
|
ref: ref,
|
|
383
394
|
tokens: getThemeTokens,
|
|
384
395
|
dataSet: dataSet,
|
|
385
|
-
backgroundImage: backgroundImage,
|
|
386
396
|
onPress: onPress,
|
|
387
397
|
href: interactiveCard?.href,
|
|
388
398
|
hrefAttrs: interactiveCard?.hrefAttrs,
|
|
@@ -391,9 +401,12 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
391
401
|
children: typeof interactiveCard?.body === 'function' ? interactiveCard.body(cardState) : interactiveCard.body
|
|
392
402
|
})
|
|
393
403
|
}), children && fullBleedContentPosition === POSITION.NONE && !fullBleedInteractive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
|
|
394
|
-
tokens: tokens,
|
|
404
|
+
tokens: getCardContentTokens(tokens, {
|
|
405
|
+
backgroundImage
|
|
406
|
+
}),
|
|
395
407
|
variant: variant,
|
|
396
408
|
withFooter: hasFooter,
|
|
409
|
+
backgroundImage: backgroundImage,
|
|
397
410
|
children: children
|
|
398
411
|
}) : null]
|
|
399
412
|
}) : null, fullBleedInteractive ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.PressableCardBase, {
|
|
@@ -436,6 +449,7 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
436
449
|
},
|
|
437
450
|
variant: variant,
|
|
438
451
|
withFooter: hasFooter,
|
|
452
|
+
backgroundImage: backgroundImage,
|
|
439
453
|
children: children
|
|
440
454
|
})
|
|
441
455
|
}) : null, fullBleedContentPosition !== POSITION.NONE && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
|
|
@@ -466,6 +480,7 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
466
480
|
}),
|
|
467
481
|
variant: variant,
|
|
468
482
|
withFooter: hasFooter,
|
|
483
|
+
backgroundImage: backgroundImage,
|
|
469
484
|
children: children
|
|
470
485
|
}) : null, !fullBleedInteractive && fullBleedContentPosition !== POSITION.NONE ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_componentsBase.StackView, {
|
|
471
486
|
direction: contentStackDirection,
|
|
@@ -477,10 +492,12 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
477
492
|
condition: isImageWidthAdjustable,
|
|
478
493
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
|
|
479
494
|
tokens: getCardContentTokens(tokens, {
|
|
495
|
+
backgroundImage,
|
|
480
496
|
fullBleedContentChildrenAlign
|
|
481
497
|
}),
|
|
482
498
|
variant: variant,
|
|
483
499
|
withFooter: hasFooter,
|
|
500
|
+
backgroundImage: backgroundImage,
|
|
484
501
|
children: children
|
|
485
502
|
})
|
|
486
503
|
}) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_ConditionalWrapper.default, {
|
|
@@ -63,6 +63,7 @@ const CardContent = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
63
63
|
tokens,
|
|
64
64
|
variant,
|
|
65
65
|
withFooter = false,
|
|
66
|
+
backgroundImage,
|
|
66
67
|
...rest
|
|
67
68
|
} = _ref2;
|
|
68
69
|
const {
|
|
@@ -71,10 +72,32 @@ const CardContent = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
71
72
|
}
|
|
72
73
|
} = (0, _componentsBase.useTheme)();
|
|
73
74
|
const allTokens = (0, _componentsBase.useAllViewportTokens)('Card', tokens, variant);
|
|
75
|
+
|
|
76
|
+
// Override backgroundColor if explicitly set in tokens to ensure it takes priority over theme tokens
|
|
77
|
+
// This is crucial for scenarios with backgroundImage where we need transparency
|
|
78
|
+
if (tokens.backgroundColor !== undefined) {
|
|
79
|
+
allTokens.current.backgroundColor = tokens.backgroundColor;
|
|
80
|
+
allTokens.xs.backgroundColor = tokens.backgroundColor;
|
|
81
|
+
allTokens.sm.backgroundColor = tokens.backgroundColor;
|
|
82
|
+
allTokens.md.backgroundColor = tokens.backgroundColor;
|
|
83
|
+
allTokens.lg.backgroundColor = tokens.backgroundColor;
|
|
84
|
+
allTokens.xl.backgroundColor = tokens.backgroundColor;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// When backgroundImage is present on the Card, ensure CardContent background is transparent
|
|
88
|
+
// so the background image from the parent CardBase can show through
|
|
89
|
+
if (backgroundImage) {
|
|
90
|
+
allTokens.current.backgroundColor = 'transparent';
|
|
91
|
+
allTokens.xs.backgroundColor = 'transparent';
|
|
92
|
+
allTokens.sm.backgroundColor = 'transparent';
|
|
93
|
+
allTokens.md.backgroundColor = 'transparent';
|
|
94
|
+
allTokens.lg.backgroundColor = 'transparent';
|
|
95
|
+
allTokens.xl.backgroundColor = 'transparent';
|
|
96
|
+
}
|
|
74
97
|
let themeTokens;
|
|
75
98
|
let mediaIds;
|
|
76
99
|
if (enableMediaQueryStyleSheet) {
|
|
77
|
-
const
|
|
100
|
+
const paddingAdjustments = {
|
|
78
101
|
xs: {
|
|
79
102
|
paddingBottom: allTokens.xs.paddingBottom - allTokens.xs.borderWidth,
|
|
80
103
|
paddingLeft: allTokens.xs.paddingLeft - allTokens.xs.borderWidth,
|
|
@@ -106,15 +129,16 @@ const CardContent = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
106
129
|
paddingTop: allTokens.xl.paddingTop - allTokens.xl.borderWidth
|
|
107
130
|
}
|
|
108
131
|
};
|
|
109
|
-
const mediaQueryStyles = (0, _componentsBase.createMediaQueryStyles)(
|
|
132
|
+
const mediaQueryStyles = (0, _componentsBase.createMediaQueryStyles)(paddingAdjustments);
|
|
133
|
+
const baseStyle = {
|
|
134
|
+
...allTokens.current,
|
|
135
|
+
...mediaQueryStyles
|
|
136
|
+
};
|
|
110
137
|
const {
|
|
111
138
|
ids,
|
|
112
139
|
styles
|
|
113
140
|
} = _componentsBase.StyleSheet.create({
|
|
114
|
-
cardContent:
|
|
115
|
-
...allTokens.current,
|
|
116
|
-
...mediaQueryStyles
|
|
117
|
-
}
|
|
141
|
+
cardContent: baseStyle
|
|
118
142
|
});
|
|
119
143
|
themeTokens = styles.cardContent;
|
|
120
144
|
mediaIds = ids.cardContent;
|
|
@@ -152,6 +176,11 @@ CardContent.propTypes = {
|
|
|
152
176
|
/**
|
|
153
177
|
* Whether the card has a footer.
|
|
154
178
|
*/
|
|
155
|
-
withFooter: _propTypes.default.bool
|
|
179
|
+
withFooter: _propTypes.default.bool,
|
|
180
|
+
/**
|
|
181
|
+
* Background image object from parent Card component.
|
|
182
|
+
* When present, makes the CardContent background transparent.
|
|
183
|
+
*/
|
|
184
|
+
backgroundImage: _propTypes.default.object
|
|
156
185
|
};
|
|
157
186
|
var _default = exports.default = CardContent;
|
|
@@ -226,7 +226,8 @@ Testimonial.propTypes = {
|
|
|
226
226
|
testimonialStyle: _propTypes.default.oneOf(['large', 'heading']),
|
|
227
227
|
/**
|
|
228
228
|
* Whether to show or not dividers at the top and the bottom of the testimonial
|
|
229
|
-
|
|
229
|
+
*/
|
|
230
|
+
showDivider: _propTypes.default.bool,
|
|
230
231
|
/**
|
|
231
232
|
* The src attribute for the Image component or custom JSX content to render instead
|
|
232
233
|
*/
|
package/lib/esm/Card/Card.js
CHANGED
|
@@ -50,11 +50,9 @@ const getCardContentTokens = function (baseTokens) {
|
|
|
50
50
|
// Determine background color based on conditions
|
|
51
51
|
let backgroundColorOverride = {};
|
|
52
52
|
if (useTransparentBackground) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
};
|
|
57
|
-
}
|
|
53
|
+
backgroundColorOverride = {
|
|
54
|
+
backgroundColor: 'transparent'
|
|
55
|
+
};
|
|
58
56
|
} else if (backgroundImage) {
|
|
59
57
|
backgroundColorOverride = {
|
|
60
58
|
backgroundColor: 'transparent'
|
|
@@ -228,7 +226,11 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
228
226
|
|
|
229
227
|
// If the card has rounded corners and a full bleed image, we need to apply
|
|
230
228
|
// those corners on the image as well, but partially
|
|
231
|
-
const
|
|
229
|
+
const variantForTokens = backgroundImage ? {
|
|
230
|
+
...variant,
|
|
231
|
+
style: undefined
|
|
232
|
+
} : variant;
|
|
233
|
+
const allThemeTokens = useThemeTokens('Card', tokens, variantForTokens);
|
|
232
234
|
const {
|
|
233
235
|
borderRadius
|
|
234
236
|
} = allThemeTokens;
|
|
@@ -281,16 +283,17 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
281
283
|
interactive: true
|
|
282
284
|
});
|
|
283
285
|
|
|
284
|
-
//
|
|
285
|
-
|
|
286
|
-
const {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
286
|
+
// Keep backgroundColor for CardContent, it won't affect FullBleedContent image
|
|
287
|
+
const tokensWithoutBg = tokens;
|
|
288
|
+
const fullBleedInteractiveVariant = backgroundImage ? {
|
|
289
|
+
...variant,
|
|
290
|
+
interactive: true,
|
|
291
|
+
style: undefined
|
|
292
|
+
} : {
|
|
291
293
|
...variant,
|
|
292
294
|
interactive: true
|
|
293
|
-
}
|
|
295
|
+
};
|
|
296
|
+
const getFullBleedInteractiveTokens = useThemeTokensCallback('Card', tokensWithoutBg, fullBleedInteractiveVariant);
|
|
294
297
|
const getFullBleedInteractiveCardTokens = cardState => {
|
|
295
298
|
return {
|
|
296
299
|
...getFullBleedInteractiveTokens(cardState),
|
|
@@ -334,8 +337,16 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
334
337
|
};
|
|
335
338
|
const cardBaseTokens = Object.fromEntries(Object.entries(tokens).filter(_ref4 => {
|
|
336
339
|
let [key] = _ref4;
|
|
337
|
-
return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage
|
|
340
|
+
return !['paddingTop', 'paddingBottom', 'paddingLeft', 'paddingRight', ...(backgroundImage ? ['backgroundColor', 'gradient', 'backgroundGradient'] : [])].includes(key);
|
|
338
341
|
}));
|
|
342
|
+
const cardBaseVariant = backgroundImage ? {
|
|
343
|
+
...(interactiveCard?.body ? mergedVariant : variant),
|
|
344
|
+
padding: 'custom',
|
|
345
|
+
style: undefined
|
|
346
|
+
} : {
|
|
347
|
+
...(interactiveCard?.body ? mergedVariant : variant),
|
|
348
|
+
padding: 'custom'
|
|
349
|
+
};
|
|
339
350
|
const isHorizontalFullBleed = fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT;
|
|
340
351
|
const isVerticalFullBleed = fullBleedContentPosition === POSITION.TOP || fullBleedContentPosition === POSITION.BOTTOM;
|
|
341
352
|
const imageWrapperStyleProps = {
|
|
@@ -352,12 +363,9 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
352
363
|
};
|
|
353
364
|
return /*#__PURE__*/_jsxs(CardBase, {
|
|
354
365
|
ref: ref,
|
|
355
|
-
variant:
|
|
356
|
-
...(interactiveCard?.body ? mergedVariant : variant),
|
|
357
|
-
padding: 'custom'
|
|
358
|
-
},
|
|
366
|
+
variant: cardBaseVariant,
|
|
359
367
|
tokens: cardBaseTokens,
|
|
360
|
-
backgroundImage:
|
|
368
|
+
backgroundImage: backgroundImage,
|
|
361
369
|
onPress: fullBleedInteractive ? undefined : onPress,
|
|
362
370
|
...(interactiveCard?.selectionType && {
|
|
363
371
|
interactiveCard,
|
|
@@ -365,16 +373,18 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
365
373
|
}),
|
|
366
374
|
...selectProps(restProps),
|
|
367
375
|
children: [interactiveCard?.selectionType && children ? /*#__PURE__*/_jsx(CardContent, {
|
|
368
|
-
tokens: tokens,
|
|
376
|
+
tokens: getCardContentTokens(tokens, {
|
|
377
|
+
backgroundImage
|
|
378
|
+
}),
|
|
369
379
|
variant: variant,
|
|
370
380
|
withFooter: hasFooter,
|
|
381
|
+
backgroundImage: backgroundImage,
|
|
371
382
|
children: children
|
|
372
383
|
}) : null, interactiveCard?.body && !interactiveCard.selectionType ? /*#__PURE__*/_jsxs(_Fragment, {
|
|
373
384
|
children: [/*#__PURE__*/_jsx(PressableCardBase, {
|
|
374
385
|
ref: ref,
|
|
375
386
|
tokens: getThemeTokens,
|
|
376
387
|
dataSet: dataSet,
|
|
377
|
-
backgroundImage: backgroundImage,
|
|
378
388
|
onPress: onPress,
|
|
379
389
|
href: interactiveCard?.href,
|
|
380
390
|
hrefAttrs: interactiveCard?.hrefAttrs,
|
|
@@ -383,9 +393,12 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
383
393
|
children: typeof interactiveCard?.body === 'function' ? interactiveCard.body(cardState) : interactiveCard.body
|
|
384
394
|
})
|
|
385
395
|
}), children && fullBleedContentPosition === POSITION.NONE && !fullBleedInteractive ? /*#__PURE__*/_jsx(CardContent, {
|
|
386
|
-
tokens: tokens,
|
|
396
|
+
tokens: getCardContentTokens(tokens, {
|
|
397
|
+
backgroundImage
|
|
398
|
+
}),
|
|
387
399
|
variant: variant,
|
|
388
400
|
withFooter: hasFooter,
|
|
401
|
+
backgroundImage: backgroundImage,
|
|
389
402
|
children: children
|
|
390
403
|
}) : null]
|
|
391
404
|
}) : null, fullBleedInteractive ? /*#__PURE__*/_jsx(PressableCardBase, {
|
|
@@ -428,6 +441,7 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
428
441
|
},
|
|
429
442
|
variant: variant,
|
|
430
443
|
withFooter: hasFooter,
|
|
444
|
+
backgroundImage: backgroundImage,
|
|
431
445
|
children: children
|
|
432
446
|
})
|
|
433
447
|
}) : null, fullBleedContentPosition !== POSITION.NONE && /*#__PURE__*/_jsx(ConditionalWrapper, {
|
|
@@ -458,6 +472,7 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
458
472
|
}),
|
|
459
473
|
variant: variant,
|
|
460
474
|
withFooter: hasFooter,
|
|
475
|
+
backgroundImage: backgroundImage,
|
|
461
476
|
children: children
|
|
462
477
|
}) : null, !fullBleedInteractive && fullBleedContentPosition !== POSITION.NONE ? /*#__PURE__*/_jsxs(StackView, {
|
|
463
478
|
direction: contentStackDirection,
|
|
@@ -469,10 +484,12 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
469
484
|
condition: isImageWidthAdjustable,
|
|
470
485
|
children: /*#__PURE__*/_jsx(CardContent, {
|
|
471
486
|
tokens: getCardContentTokens(tokens, {
|
|
487
|
+
backgroundImage,
|
|
472
488
|
fullBleedContentChildrenAlign
|
|
473
489
|
}),
|
|
474
490
|
variant: variant,
|
|
475
491
|
withFooter: hasFooter,
|
|
492
|
+
backgroundImage: backgroundImage,
|
|
476
493
|
children: children
|
|
477
494
|
})
|
|
478
495
|
}) : null, /*#__PURE__*/_jsx(ConditionalWrapper, {
|
|
@@ -56,6 +56,7 @@ const CardContent = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
56
56
|
tokens,
|
|
57
57
|
variant,
|
|
58
58
|
withFooter = false,
|
|
59
|
+
backgroundImage,
|
|
59
60
|
...rest
|
|
60
61
|
} = _ref2;
|
|
61
62
|
const {
|
|
@@ -64,10 +65,32 @@ const CardContent = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
64
65
|
}
|
|
65
66
|
} = useTheme();
|
|
66
67
|
const allTokens = useAllViewportTokens('Card', tokens, variant);
|
|
68
|
+
|
|
69
|
+
// Override backgroundColor if explicitly set in tokens to ensure it takes priority over theme tokens
|
|
70
|
+
// This is crucial for scenarios with backgroundImage where we need transparency
|
|
71
|
+
if (tokens.backgroundColor !== undefined) {
|
|
72
|
+
allTokens.current.backgroundColor = tokens.backgroundColor;
|
|
73
|
+
allTokens.xs.backgroundColor = tokens.backgroundColor;
|
|
74
|
+
allTokens.sm.backgroundColor = tokens.backgroundColor;
|
|
75
|
+
allTokens.md.backgroundColor = tokens.backgroundColor;
|
|
76
|
+
allTokens.lg.backgroundColor = tokens.backgroundColor;
|
|
77
|
+
allTokens.xl.backgroundColor = tokens.backgroundColor;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// When backgroundImage is present on the Card, ensure CardContent background is transparent
|
|
81
|
+
// so the background image from the parent CardBase can show through
|
|
82
|
+
if (backgroundImage) {
|
|
83
|
+
allTokens.current.backgroundColor = 'transparent';
|
|
84
|
+
allTokens.xs.backgroundColor = 'transparent';
|
|
85
|
+
allTokens.sm.backgroundColor = 'transparent';
|
|
86
|
+
allTokens.md.backgroundColor = 'transparent';
|
|
87
|
+
allTokens.lg.backgroundColor = 'transparent';
|
|
88
|
+
allTokens.xl.backgroundColor = 'transparent';
|
|
89
|
+
}
|
|
67
90
|
let themeTokens;
|
|
68
91
|
let mediaIds;
|
|
69
92
|
if (enableMediaQueryStyleSheet) {
|
|
70
|
-
const
|
|
93
|
+
const paddingAdjustments = {
|
|
71
94
|
xs: {
|
|
72
95
|
paddingBottom: allTokens.xs.paddingBottom - allTokens.xs.borderWidth,
|
|
73
96
|
paddingLeft: allTokens.xs.paddingLeft - allTokens.xs.borderWidth,
|
|
@@ -99,15 +122,16 @@ const CardContent = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
99
122
|
paddingTop: allTokens.xl.paddingTop - allTokens.xl.borderWidth
|
|
100
123
|
}
|
|
101
124
|
};
|
|
102
|
-
const mediaQueryStyles = createMediaQueryStyles(
|
|
125
|
+
const mediaQueryStyles = createMediaQueryStyles(paddingAdjustments);
|
|
126
|
+
const baseStyle = {
|
|
127
|
+
...allTokens.current,
|
|
128
|
+
...mediaQueryStyles
|
|
129
|
+
};
|
|
103
130
|
const {
|
|
104
131
|
ids,
|
|
105
132
|
styles
|
|
106
133
|
} = StyleSheet.create({
|
|
107
|
-
cardContent:
|
|
108
|
-
...allTokens.current,
|
|
109
|
-
...mediaQueryStyles
|
|
110
|
-
}
|
|
134
|
+
cardContent: baseStyle
|
|
111
135
|
});
|
|
112
136
|
themeTokens = styles.cardContent;
|
|
113
137
|
mediaIds = ids.cardContent;
|
|
@@ -145,6 +169,11 @@ CardContent.propTypes = {
|
|
|
145
169
|
/**
|
|
146
170
|
* Whether the card has a footer.
|
|
147
171
|
*/
|
|
148
|
-
withFooter: PropTypes.bool
|
|
172
|
+
withFooter: PropTypes.bool,
|
|
173
|
+
/**
|
|
174
|
+
* Background image object from parent Card component.
|
|
175
|
+
* When present, makes the CardContent background transparent.
|
|
176
|
+
*/
|
|
177
|
+
backgroundImage: PropTypes.object
|
|
149
178
|
};
|
|
150
179
|
export default CardContent;
|
|
@@ -219,6 +219,7 @@ Testimonial.propTypes = {
|
|
|
219
219
|
testimonialStyle: PropTypes.oneOf(['large', 'heading']),
|
|
220
220
|
/**
|
|
221
221
|
* Whether to show or not dividers at the top and the bottom of the testimonial
|
|
222
|
+
*/
|
|
222
223
|
showDivider: PropTypes.bool,
|
|
223
224
|
/**
|
|
224
225
|
* The src attribute for the Image component or custom JSX content to render instead
|
package/package.json
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
],
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@gorhom/portal": "^1.0.14",
|
|
8
|
-
"@telus-uds/components-base": "^3.
|
|
8
|
+
"@telus-uds/components-base": "^3.28.0",
|
|
9
9
|
"@telus-uds/system-constants": "^3.0.0",
|
|
10
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
10
|
+
"@telus-uds/system-theme-tokens": "^4.20.0",
|
|
11
11
|
"fscreen": "^1.2.0",
|
|
12
12
|
"lodash.omit": "^4.5.0",
|
|
13
13
|
"lodash.throttle": "^4.1.1",
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"skip": true
|
|
83
83
|
},
|
|
84
84
|
"types": "types/index.d.ts",
|
|
85
|
-
"version": "4.18.
|
|
85
|
+
"version": "4.18.1"
|
|
86
86
|
}
|
package/src/Card/Card.jsx
CHANGED
|
@@ -64,9 +64,7 @@ const getCardContentTokens = (baseTokens, options = {}) => {
|
|
|
64
64
|
// Determine background color based on conditions
|
|
65
65
|
let backgroundColorOverride = {}
|
|
66
66
|
if (useTransparentBackground) {
|
|
67
|
-
|
|
68
|
-
backgroundColorOverride = { backgroundColor: 'transparent' }
|
|
69
|
-
}
|
|
67
|
+
backgroundColorOverride = { backgroundColor: 'transparent' }
|
|
70
68
|
} else if (backgroundImage) {
|
|
71
69
|
backgroundColorOverride = { backgroundColor: 'transparent' }
|
|
72
70
|
}
|
|
@@ -218,7 +216,8 @@ const Card = React.forwardRef(
|
|
|
218
216
|
|
|
219
217
|
// If the card has rounded corners and a full bleed image, we need to apply
|
|
220
218
|
// those corners on the image as well, but partially
|
|
221
|
-
const
|
|
219
|
+
const variantForTokens = backgroundImage ? { ...variant, style: undefined } : variant
|
|
220
|
+
const allThemeTokens = useThemeTokens('Card', tokens, variantForTokens)
|
|
222
221
|
const { borderRadius } = allThemeTokens
|
|
223
222
|
|
|
224
223
|
// Interactive cards: merge variants for CardBase (outer container)
|
|
@@ -274,14 +273,25 @@ const Card = React.forwardRef(
|
|
|
274
273
|
}
|
|
275
274
|
)
|
|
276
275
|
|
|
277
|
-
//
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
276
|
+
// Keep backgroundColor for CardContent, it won't affect FullBleedContent image
|
|
277
|
+
const tokensWithoutBg = tokens
|
|
278
|
+
|
|
279
|
+
const fullBleedInteractiveVariant = backgroundImage
|
|
280
|
+
? {
|
|
281
|
+
...variant,
|
|
282
|
+
interactive: true,
|
|
283
|
+
style: undefined
|
|
284
|
+
}
|
|
285
|
+
: {
|
|
286
|
+
...variant,
|
|
287
|
+
interactive: true
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const getFullBleedInteractiveTokens = useThemeTokensCallback(
|
|
291
|
+
'Card',
|
|
292
|
+
tokensWithoutBg,
|
|
293
|
+
fullBleedInteractiveVariant
|
|
294
|
+
)
|
|
285
295
|
|
|
286
296
|
const getFullBleedInteractiveCardTokens = (cardState) => {
|
|
287
297
|
return {
|
|
@@ -343,11 +353,19 @@ const Card = React.forwardRef(
|
|
|
343
353
|
'paddingBottom',
|
|
344
354
|
'paddingLeft',
|
|
345
355
|
'paddingRight',
|
|
346
|
-
...(backgroundImage
|
|
356
|
+
...(backgroundImage ? ['backgroundColor', 'gradient', 'backgroundGradient'] : [])
|
|
347
357
|
].includes(key)
|
|
348
358
|
)
|
|
349
359
|
)
|
|
350
360
|
|
|
361
|
+
const cardBaseVariant = backgroundImage
|
|
362
|
+
? {
|
|
363
|
+
...(interactiveCard?.body ? mergedVariant : variant),
|
|
364
|
+
padding: 'custom',
|
|
365
|
+
style: undefined
|
|
366
|
+
}
|
|
367
|
+
: { ...(interactiveCard?.body ? mergedVariant : variant), padding: 'custom' }
|
|
368
|
+
|
|
351
369
|
const isHorizontalFullBleed =
|
|
352
370
|
fullBleedContentPosition === POSITION.LEFT || fullBleedContentPosition === POSITION.RIGHT
|
|
353
371
|
const isVerticalFullBleed =
|
|
@@ -363,15 +381,20 @@ const Card = React.forwardRef(
|
|
|
363
381
|
return (
|
|
364
382
|
<CardBase
|
|
365
383
|
ref={ref}
|
|
366
|
-
variant={
|
|
384
|
+
variant={cardBaseVariant}
|
|
367
385
|
tokens={cardBaseTokens}
|
|
368
|
-
backgroundImage={
|
|
386
|
+
backgroundImage={backgroundImage}
|
|
369
387
|
onPress={fullBleedInteractive ? undefined : onPress}
|
|
370
388
|
{...(interactiveCard?.selectionType && { interactiveCard, id: rest.id })}
|
|
371
389
|
{...selectProps(restProps)}
|
|
372
390
|
>
|
|
373
391
|
{interactiveCard?.selectionType && children ? (
|
|
374
|
-
<CardContent
|
|
392
|
+
<CardContent
|
|
393
|
+
tokens={getCardContentTokens(tokens, { backgroundImage })}
|
|
394
|
+
variant={variant}
|
|
395
|
+
withFooter={hasFooter}
|
|
396
|
+
backgroundImage={backgroundImage}
|
|
397
|
+
>
|
|
375
398
|
{children}
|
|
376
399
|
</CardContent>
|
|
377
400
|
) : null}
|
|
@@ -381,7 +404,6 @@ const Card = React.forwardRef(
|
|
|
381
404
|
ref={ref}
|
|
382
405
|
tokens={getThemeTokens}
|
|
383
406
|
dataSet={dataSet}
|
|
384
|
-
backgroundImage={backgroundImage}
|
|
385
407
|
onPress={onPress}
|
|
386
408
|
href={interactiveCard?.href}
|
|
387
409
|
hrefAttrs={interactiveCard?.hrefAttrs}
|
|
@@ -396,7 +418,12 @@ const Card = React.forwardRef(
|
|
|
396
418
|
)}
|
|
397
419
|
</PressableCardBase>
|
|
398
420
|
{children && fullBleedContentPosition === POSITION.NONE && !fullBleedInteractive ? (
|
|
399
|
-
<CardContent
|
|
421
|
+
<CardContent
|
|
422
|
+
tokens={getCardContentTokens(tokens, { backgroundImage })}
|
|
423
|
+
variant={variant}
|
|
424
|
+
withFooter={hasFooter}
|
|
425
|
+
backgroundImage={backgroundImage}
|
|
426
|
+
>
|
|
400
427
|
{children}
|
|
401
428
|
</CardContent>
|
|
402
429
|
) : null}
|
|
@@ -462,6 +489,7 @@ const Card = React.forwardRef(
|
|
|
462
489
|
}}
|
|
463
490
|
variant={variant}
|
|
464
491
|
withFooter={hasFooter}
|
|
492
|
+
backgroundImage={backgroundImage}
|
|
465
493
|
>
|
|
466
494
|
{children}
|
|
467
495
|
</CardContent>
|
|
@@ -508,6 +536,7 @@ const Card = React.forwardRef(
|
|
|
508
536
|
})}
|
|
509
537
|
variant={variant}
|
|
510
538
|
withFooter={hasFooter}
|
|
539
|
+
backgroundImage={backgroundImage}
|
|
511
540
|
>
|
|
512
541
|
{children}
|
|
513
542
|
</CardContent>
|
|
@@ -526,10 +555,12 @@ const Card = React.forwardRef(
|
|
|
526
555
|
>
|
|
527
556
|
<CardContent
|
|
528
557
|
tokens={getCardContentTokens(tokens, {
|
|
558
|
+
backgroundImage,
|
|
529
559
|
fullBleedContentChildrenAlign
|
|
530
560
|
})}
|
|
531
561
|
variant={variant}
|
|
532
562
|
withFooter={hasFooter}
|
|
563
|
+
backgroundImage={backgroundImage}
|
|
533
564
|
>
|
|
534
565
|
{children}
|
|
535
566
|
</CardContent>
|
package/src/Card/CardContent.jsx
CHANGED
|
@@ -55,18 +55,43 @@ const CardContentContainer = styled.div(
|
|
|
55
55
|
* Card content, applying the card tokens as per the theme used.
|
|
56
56
|
*/
|
|
57
57
|
const CardContent = React.forwardRef(
|
|
58
|
-
(
|
|
58
|
+
(
|
|
59
|
+
{ children, flexContent, tokens, variant, withFooter = false, backgroundImage, ...rest },
|
|
60
|
+
ref
|
|
61
|
+
) => {
|
|
59
62
|
const {
|
|
60
63
|
themeOptions: { enableMediaQueryStyleSheet }
|
|
61
64
|
} = useTheme()
|
|
62
65
|
|
|
63
66
|
const allTokens = useAllViewportTokens('Card', tokens, variant)
|
|
64
67
|
|
|
68
|
+
// Override backgroundColor if explicitly set in tokens to ensure it takes priority over theme tokens
|
|
69
|
+
// This is crucial for scenarios with backgroundImage where we need transparency
|
|
70
|
+
if (tokens.backgroundColor !== undefined) {
|
|
71
|
+
allTokens.current.backgroundColor = tokens.backgroundColor
|
|
72
|
+
allTokens.xs.backgroundColor = tokens.backgroundColor
|
|
73
|
+
allTokens.sm.backgroundColor = tokens.backgroundColor
|
|
74
|
+
allTokens.md.backgroundColor = tokens.backgroundColor
|
|
75
|
+
allTokens.lg.backgroundColor = tokens.backgroundColor
|
|
76
|
+
allTokens.xl.backgroundColor = tokens.backgroundColor
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// When backgroundImage is present on the Card, ensure CardContent background is transparent
|
|
80
|
+
// so the background image from the parent CardBase can show through
|
|
81
|
+
if (backgroundImage) {
|
|
82
|
+
allTokens.current.backgroundColor = 'transparent'
|
|
83
|
+
allTokens.xs.backgroundColor = 'transparent'
|
|
84
|
+
allTokens.sm.backgroundColor = 'transparent'
|
|
85
|
+
allTokens.md.backgroundColor = 'transparent'
|
|
86
|
+
allTokens.lg.backgroundColor = 'transparent'
|
|
87
|
+
allTokens.xl.backgroundColor = 'transparent'
|
|
88
|
+
}
|
|
89
|
+
|
|
65
90
|
let themeTokens
|
|
66
91
|
let mediaIds
|
|
67
92
|
|
|
68
93
|
if (enableMediaQueryStyleSheet) {
|
|
69
|
-
const
|
|
94
|
+
const paddingAdjustments = {
|
|
70
95
|
xs: {
|
|
71
96
|
paddingBottom: allTokens.xs.paddingBottom - allTokens.xs.borderWidth,
|
|
72
97
|
paddingLeft: allTokens.xs.paddingLeft - allTokens.xs.borderWidth,
|
|
@@ -99,12 +124,14 @@ const CardContent = React.forwardRef(
|
|
|
99
124
|
}
|
|
100
125
|
}
|
|
101
126
|
|
|
102
|
-
const mediaQueryStyles = createMediaQueryStyles(
|
|
127
|
+
const mediaQueryStyles = createMediaQueryStyles(paddingAdjustments)
|
|
128
|
+
const baseStyle = {
|
|
129
|
+
...allTokens.current,
|
|
130
|
+
...mediaQueryStyles
|
|
131
|
+
}
|
|
132
|
+
|
|
103
133
|
const { ids, styles } = StyleSheet.create({
|
|
104
|
-
cardContent:
|
|
105
|
-
...allTokens.current,
|
|
106
|
-
...mediaQueryStyles
|
|
107
|
-
}
|
|
134
|
+
cardContent: baseStyle
|
|
108
135
|
})
|
|
109
136
|
|
|
110
137
|
themeTokens = styles.cardContent
|
|
@@ -151,7 +178,12 @@ CardContent.propTypes = {
|
|
|
151
178
|
/**
|
|
152
179
|
* Whether the card has a footer.
|
|
153
180
|
*/
|
|
154
|
-
withFooter: PropTypes.bool
|
|
181
|
+
withFooter: PropTypes.bool,
|
|
182
|
+
/**
|
|
183
|
+
* Background image object from parent Card component.
|
|
184
|
+
* When present, makes the CardContent background transparent.
|
|
185
|
+
*/
|
|
186
|
+
backgroundImage: PropTypes.object
|
|
155
187
|
}
|
|
156
188
|
|
|
157
189
|
export default CardContent
|
|
@@ -229,6 +229,7 @@ Testimonial.propTypes = {
|
|
|
229
229
|
testimonialStyle: PropTypes.oneOf(['large', 'heading']),
|
|
230
230
|
/**
|
|
231
231
|
* Whether to show or not dividers at the top and the bottom of the testimonial
|
|
232
|
+
*/
|
|
232
233
|
showDivider: PropTypes.bool,
|
|
233
234
|
/**
|
|
234
235
|
* The src attribute for the Image component or custom JSX content to render instead
|