@telus-uds/components-base 3.27.0 → 3.28.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +21 -5
  2. package/lib/cjs/Card/CardBase.js +12 -3
  3. package/lib/cjs/ExpandCollapse/Control.js +5 -1
  4. package/lib/cjs/ExpandCollapse/ExpandCollapse.js +17 -8
  5. package/lib/cjs/ExpandCollapse/Panel.js +7 -2
  6. package/lib/cjs/IconButton/IconButton.js +10 -5
  7. package/lib/cjs/Modal/Modal.js +21 -11
  8. package/lib/cjs/Progress/Progress.js +19 -5
  9. package/lib/cjs/Progress/ProgressBar.js +22 -4
  10. package/lib/cjs/Progress/ProgressContext.js +11 -0
  11. package/lib/cjs/SideNav/Item.js +3 -3
  12. package/lib/cjs/SideNav/ItemsGroup.js +46 -19
  13. package/lib/cjs/SideNav/SideNav.js +29 -13
  14. package/lib/esm/Card/CardBase.js +12 -3
  15. package/lib/esm/ExpandCollapse/Control.js +5 -1
  16. package/lib/esm/ExpandCollapse/ExpandCollapse.js +17 -8
  17. package/lib/esm/ExpandCollapse/Panel.js +7 -2
  18. package/lib/esm/IconButton/IconButton.js +10 -5
  19. package/lib/esm/Modal/Modal.js +21 -11
  20. package/lib/esm/Progress/Progress.js +19 -5
  21. package/lib/esm/Progress/ProgressBar.js +22 -4
  22. package/lib/esm/Progress/ProgressContext.js +5 -0
  23. package/lib/esm/SideNav/Item.js +3 -3
  24. package/lib/esm/SideNav/ItemsGroup.js +45 -20
  25. package/lib/esm/SideNav/SideNav.js +29 -13
  26. package/lib/package.json +2 -2
  27. package/package.json +2 -2
  28. package/src/Card/CardBase.jsx +9 -3
  29. package/src/ExpandCollapse/Control.jsx +1 -1
  30. package/src/ExpandCollapse/ExpandCollapse.jsx +9 -8
  31. package/src/ExpandCollapse/Panel.jsx +10 -2
  32. package/src/IconButton/IconButton.jsx +40 -28
  33. package/src/Modal/Modal.jsx +23 -11
  34. package/src/Progress/Progress.jsx +18 -7
  35. package/src/Progress/ProgressBar.jsx +19 -14
  36. package/src/Progress/ProgressContext.js +5 -0
  37. package/src/SideNav/Item.jsx +3 -3
  38. package/src/SideNav/ItemsGroup.jsx +36 -16
  39. package/src/SideNav/SideNav.jsx +22 -8
@@ -6,13 +6,22 @@ import { useThemeTokens } from '../ThemeProvider';
6
6
  import { a11yProps, getTokensPropType, selectSystemProps, useMultipleInputValues, variantProp, viewProps, contentfulProps, useUniqueId } from '../utils';
7
7
  import { jsx as _jsx } from "react/jsx-runtime";
8
8
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps, contentfulProps]);
9
- function selectBorderStyles(tokens) {
9
+ const selectWrapperStyles = _ref => {
10
+ let {
11
+ borderWidth,
12
+ borderTopWidth,
13
+ borderStyle,
14
+ borderColor
15
+ } = _ref;
10
16
  return {
11
- borderBottomWidth: tokens.borderWidth,
12
- borderBottomStyle: tokens.borderStyle,
13
- borderBottomColor: tokens.borderColor
17
+ borderStyle,
18
+ borderColor,
19
+ borderTopWidth,
20
+ borderBottomWidth: borderWidth,
21
+ borderBottomStyle: borderStyle,
22
+ borderBottomColor: borderColor
14
23
  };
15
- }
24
+ };
16
25
 
17
26
  /**
18
27
  * Flexible base component for lists where some or all items are collapsible headers.
@@ -21,7 +30,7 @@ function selectBorderStyles(tokens) {
21
30
  * <ExpandCollapse.Panel> children, and assign the panels explicit `panelId` props. The panels may be
22
31
  * nested (they do not need to be direct children), and non-interactive items may be included too.
23
32
  */
24
- const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
33
+ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
25
34
  let {
26
35
  children,
27
36
  tokens,
@@ -32,7 +41,7 @@ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
32
41
  onChange,
33
42
  dataSet,
34
43
  ...rest
35
- } = _ref;
44
+ } = _ref2;
36
45
  const instanceId = useUniqueId('ExpandCollapse');
37
46
  const {
38
47
  currentValues: openIds,
@@ -53,7 +62,7 @@ const ExpandCollapse = /*#__PURE__*/React.forwardRef((_ref, ref) => {
53
62
  ...selectProps(rest),
54
63
  dataSet: dataSet,
55
64
  children: /*#__PURE__*/_jsx(View, {
56
- style: selectBorderStyles(themeTokens),
65
+ style: selectWrapperStyles(themeTokens),
57
66
  children: typeof children === 'function' ? children({
58
67
  openIds,
59
68
  onToggle,
@@ -103,6 +103,7 @@ const ExpandCollapsePanel = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
103
103
  controlRef,
104
104
  content,
105
105
  copy = 'en',
106
+ disableMobileScrollBuffer = false,
106
107
  ...rest
107
108
  } = _ref5;
108
109
  const [containerHeight, setContainerHeight] = React.useState(null);
@@ -124,7 +125,7 @@ const ExpandCollapsePanel = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
124
125
 
125
126
  // on mobile devices we require a scroll buffer equal to the font size
126
127
  // to avoid triggering scrolling unnecessarily
127
- const mobileScrollBuffer = Platform.OS === 'web' ? 0 : selectTextStyles(themeTokens)?.fontSize;
128
+ const mobileScrollBuffer = Platform.OS === 'web' || disableMobileScrollBuffer ? 0 : selectTextStyles(themeTokens)?.fontSize;
128
129
  const handleControlPress = event => {
129
130
  onToggle?.(panelId, event);
130
131
  if (onPress) onPress(panelId, event);
@@ -271,6 +272,10 @@ ExpandCollapsePanel.propTypes = {
271
272
  /**
272
273
  * A boolean prop to determine if the panel is a content panel or not. If true, the panel will not have a control
273
274
  */
274
- content: PropTypes.bool
275
+ content: PropTypes.bool,
276
+ /**
277
+ * A boolean prop to disable the extra scroll buffer on mobile devices (only applicable on iOS/Android, ignored on web)
278
+ */
279
+ disableMobileScrollBuffer: PropTypes.bool
275
280
  };
276
281
  export default ExpandCollapsePanel;
@@ -79,6 +79,11 @@ const selectInnerStyle = (_ref2, password) => {
79
79
  width,
80
80
  height
81
81
  } = _ref2;
82
+ const basePadding = calculatePadding(padding, borderWidth);
83
+ const calculateSpecificPadding = (specificPadding, specificBorderWidth) => {
84
+ const calculated = calculatePadding(specificPadding ?? padding, specificBorderWidth ?? borderWidth);
85
+ return calculated !== basePadding && calculated !== undefined ? calculated : undefined;
86
+ };
82
87
  return {
83
88
  // Inner borders animate with the icon and should be treated like a themable feature of the icon
84
89
  borderColor,
@@ -92,11 +97,11 @@ const selectInnerStyle = (_ref2, password) => {
92
97
  borderRightWidth,
93
98
  borderBottomWidth,
94
99
  borderLeftWidth,
95
- padding: calculatePadding(padding, borderWidth),
96
- paddingLeft: calculatePadding(paddingLeft, borderLeftWidth),
97
- paddingRight: calculatePadding(paddingRight, borderRightWidth),
98
- paddingTop: calculatePadding(paddingTop, borderTopWidth),
99
- paddingBottom: calculatePadding(paddingBottom, borderBottomWidth),
100
+ padding: basePadding,
101
+ paddingLeft: calculateSpecificPadding(paddingLeft, borderLeftWidth),
102
+ paddingRight: calculateSpecificPadding(paddingRight, borderRightWidth),
103
+ paddingTop: calculateSpecificPadding(paddingTop, borderTopWidth),
104
+ paddingBottom: calculateSpecificPadding(paddingBottom, borderBottomWidth),
100
105
  ...Platform.select({
101
106
  web: {
102
107
  pointerEvents: 'none',
@@ -64,11 +64,15 @@ const selectModalStyles = _ref2 => {
64
64
  const selectBackdropStyles = _ref3 => {
65
65
  let {
66
66
  backdropColor,
67
- backdropOpacity
67
+ backdropOpacity,
68
+ backdropCursor
68
69
  } = _ref3;
69
70
  return {
70
71
  backgroundColor: backdropColor,
71
- opacity: backdropOpacity
72
+ opacity: backdropOpacity,
73
+ ...(Platform.OS === 'web' && backdropCursor ? {
74
+ cursor: backdropCursor
75
+ } : {})
72
76
  };
73
77
  };
74
78
  const selectCloseButtonContainerStyles = _ref4 => {
@@ -121,12 +125,15 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
121
125
  cancelButtonText,
122
126
  cancelButtonType,
123
127
  footer,
128
+ backgroundDismissible = true,
124
129
  ...rest
125
130
  } = _ref5;
126
131
  const viewport = useViewport();
132
+ const isBackdropClickable = onClose && backgroundDismissible;
127
133
  const themeTokens = useThemeTokens('Modal', tokens, variant, {
128
134
  viewport,
129
- maxWidth
135
+ maxWidth,
136
+ backdropCursor: isBackdropClickable ? 'pointer' : 'default'
130
137
  });
131
138
  const modalRef = useScrollBlocking(isOpen);
132
139
  const modalBodyRef = React.useRef(ref);
@@ -232,7 +239,7 @@ const Modal = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
232
239
  })]
233
240
  })
234
241
  }), /*#__PURE__*/_jsx(TouchableWithoutFeedback, {
235
- onPress: handleClose,
242
+ onPress: isBackdropClickable && handleClose,
236
243
  children: /*#__PURE__*/_jsx(View, {
237
244
  style: [staticStyles.backdrop, selectBackdropStyles(themeTokens)]
238
245
  })
@@ -329,7 +336,15 @@ Modal.propTypes = {
329
336
  /**
330
337
  * Receive a react node or an array of nodes to render at the bottom of the modal, above the action buttons.
331
338
  */
332
- footer: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)])
339
+ footer: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
340
+ /**
341
+ * Controls whether the modal can be dismissed by clicking on the backdrop.
342
+ * When set to `false`, clicking the backdrop will not close the modal.
343
+ * The backdrop cursor automatically changes to 'default' to indicate it's not clickable.
344
+ * Note: Backdrop dismissal requires `onClose` to be defined.
345
+ * @default true
346
+ */
347
+ backgroundDismissible: PropTypes.bool
333
348
  };
334
349
  export default Modal;
335
350
  const staticStyles = StyleSheet.create({
@@ -339,12 +354,7 @@ const staticStyles = StyleSheet.create({
339
354
  left: 0,
340
355
  right: 0,
341
356
  bottom: 0,
342
- zIndex: -1,
343
- ...Platform.select({
344
- web: {
345
- cursor: 'pointer'
346
- }
347
- })
357
+ zIndex: -1
348
358
  },
349
359
  positioningContainer: {
350
360
  flexBasis: '100%',
@@ -4,6 +4,7 @@ import View from "react-native-web/dist/exports/View";
4
4
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
5
  import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
6
6
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
7
+ import ProgressContext from './ProgressContext';
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
8
9
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
9
10
  const selectProgressStyles = _ref => {
@@ -47,6 +48,12 @@ const selectProgressStyles = _ref => {
47
48
  *
48
49
  * - Use the `size` variant to control the height of your progress bars: passing `'mini'` will make your
49
50
  * progress bar container narrower.
51
+ * - Use the `layers` variant to control how multiple progress bars are positioned:
52
+ * - `false` (default): bars are positioned vertically one below the other.
53
+ * - `true`: bars overlay on top of each other (layered/stacked on z-axis).
54
+ * Note: The `layers` prop is deprecated. After August 2026, `layers: true` will become the permanent
55
+ * default behavior and the `layers` prop will be removed. To maintain vertical layout after removal,
56
+ * use separate individual Progress components.
50
57
  *
51
58
  * ## Usability and A11y guidelines
52
59
  *
@@ -63,11 +70,18 @@ const Progress = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
63
70
  ...rest
64
71
  } = _ref2;
65
72
  const themeTokens = useThemeTokens('Progress', tokens, variant);
66
- return /*#__PURE__*/_jsx(View, {
67
- ref: ref,
68
- style: [staticStyles.progressContainer, selectProgressStyles(themeTokens)],
69
- ...selectProps(rest),
70
- children: children
73
+ // Default to false (vertical layout) to preserve existing behavior and avoid breaking changes
74
+ const layers = variant?.layers ?? false;
75
+ return /*#__PURE__*/_jsx(ProgressContext.Provider, {
76
+ value: {
77
+ layers
78
+ },
79
+ children: /*#__PURE__*/_jsx(View, {
80
+ ref: ref,
81
+ style: [staticStyles.progressContainer, selectProgressStyles(themeTokens)],
82
+ ...selectProps(rest),
83
+ children: children
84
+ })
71
85
  });
72
86
  });
73
87
  Progress.displayName = 'Progress';
@@ -7,16 +7,23 @@ import ProgressBarBackground from './ProgressBarBackground';
7
7
  import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
8
8
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
9
9
  import { MAX_PERCENT_VALUE, MIN_PERCENT_VALUE } from './constants';
10
+ import ProgressContext from './ProgressContext';
10
11
  import { jsx as _jsx } from "react/jsx-runtime";
11
12
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
12
- const selectBarStyles = (_ref, calculatedPercentage, barPosition) => {
13
+ const selectBarStyles = _ref => {
13
14
  let {
15
+ themeTokens,
16
+ calculatedPercentage,
17
+ barPosition,
18
+ layers
19
+ } = _ref;
20
+ const {
14
21
  backgroundColor,
15
22
  borderRadius,
16
23
  outlineWidth,
17
24
  outlineColor,
18
25
  shadow
19
- } = _ref;
26
+ } = themeTokens;
20
27
  return {
21
28
  backgroundColor,
22
29
  borderRadius,
@@ -24,7 +31,10 @@ const selectBarStyles = (_ref, calculatedPercentage, barPosition) => {
24
31
  outlineColor,
25
32
  ...applyShadowToken(shadow),
26
33
  width: `${calculatedPercentage}%`,
27
- left: `${barPosition}%`
34
+ left: `${barPosition}%`,
35
+ ...(layers ? {
36
+ position: 'absolute'
37
+ } : {})
28
38
  };
29
39
  };
30
40
 
@@ -75,6 +85,9 @@ const ProgressBar = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
75
85
  },
76
86
  ...rest
77
87
  } = _ref2;
88
+ const {
89
+ layers
90
+ } = React.useContext(ProgressContext);
78
91
  const {
79
92
  items,
80
93
  current
@@ -107,7 +120,12 @@ const ProgressBar = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
107
120
  });
108
121
  return percentage > MIN_PERCENT_VALUE || items ? /*#__PURE__*/_jsx(View, {
109
122
  ref: ref,
110
- style: [staticStyles.bar, selectBarStyles(themeTokens, calculatedPercentage, barPosition)],
123
+ style: [staticStyles.bar, selectBarStyles({
124
+ themeTokens,
125
+ calculatedPercentage,
126
+ barPosition,
127
+ layers
128
+ })],
111
129
  ...selectedProps,
112
130
  children: children ?? /*#__PURE__*/_jsx(ProgressBarBackground, {
113
131
  variant: variant
@@ -0,0 +1,5 @@
1
+ import { createContext } from 'react';
2
+ const ProgressContext = /*#__PURE__*/createContext({
3
+ layers: false
4
+ });
5
+ export default ProgressContext;
@@ -22,9 +22,9 @@ function selectItemStyles(_ref) {
22
22
  } = _ref;
23
23
  return {
24
24
  backgroundColor,
25
- borderTopColor: borderColor,
26
- borderTopWidth: borderWidth,
27
- borderTopStyle: borderStyle,
25
+ borderBottomColor: borderColor,
26
+ borderBottomWidth: borderWidth,
27
+ borderBottomStyle: borderStyle,
28
28
  paddingLeft,
29
29
  paddingRight,
30
30
  paddingTop,
@@ -4,6 +4,19 @@ import ItemContent from './ItemContent';
4
4
  import ExpandCollapse from '../ExpandCollapse';
5
5
  import { getTokensPropType, variantProp, componentPropType, selectTokens } from '../utils';
6
6
  import { useThemeTokensCallback } from '../ThemeProvider';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ const selectPanelTokens = _ref => {
9
+ let {
10
+ borderWidth,
11
+ borderColor,
12
+ backgroundColor
13
+ } = _ref;
14
+ return {
15
+ contentPanelBackgroundColor: backgroundColor,
16
+ borderBottomWidth: borderWidth,
17
+ borderColor
18
+ };
19
+ };
7
20
 
8
21
  /**
9
22
  Expandable content areas for use within `SideNav`.
@@ -15,8 +28,7 @@ import { useThemeTokensCallback } from '../ThemeProvider';
15
28
  ## Usage Criteria
16
29
  - Use `SideNav.ItemsGroup` with large pages that have multiple sections
17
30
  */
18
- import { jsx as _jsx } from "react/jsx-runtime";
19
- const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
31
+ const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
20
32
  let {
21
33
  children,
22
34
  label,
@@ -27,7 +39,7 @@ const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
27
39
  tokens,
28
40
  itemTokens,
29
41
  onToggle
30
- } = _ref;
42
+ } = _ref2;
31
43
  // A SideNav control uses the same style and theme as SideNavItem, with a 'parent' variant,
32
44
  // plus control-specific tokens from the SideNavItemsGroup theme (e.g. open/close icon, etc).
33
45
  const getAppearance = appearance => ({
@@ -40,28 +52,27 @@ const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
40
52
  type: 'parent'
41
53
  });
42
54
  const getGroupTokens = useThemeTokensCallback('SideNavItemsGroup', tokens, variant);
43
- const getPanelTokens = appearance => {
44
- const {
45
- panelBorderColor,
46
- ...itemsGroupTokens
47
- } = getGroupTokens(getAppearance(appearance));
48
- const groupTokens = {
49
- ...itemsGroupTokens,
50
- borderWidth: 0,
51
- marginBottom: 0
52
- };
53
- return selectTokens('ExpandCollapsePanel', groupTokens);
54
- };
55
55
  const getItemTokens = useThemeTokensCallback('SideNavItem', itemTokens, variant);
56
- const getControlTokens = appearance => selectTokens('ExpandCollapseControl', {
57
- ...getItemTokens(getItemAppearance(appearance)),
58
- // main style from SideNavItem
59
- ...getGroupTokens(getAppearance(appearance)) // control-specific tokens like icon etc
56
+ const getPanelTokens = appearance => selectTokens('ExpandCollapsePanel', {
57
+ ...staticTokens.panel,
58
+ ...getGroupTokens(getAppearance(appearance)),
59
+ ...selectPanelTokens(getItemTokens(getItemAppearance(appearance)))
60
+ });
61
+ const getControlTokens = appearance => ({
62
+ ...selectTokens('ExpandCollapseControl', {
63
+ ...getItemTokens(getItemAppearance(appearance)),
64
+ // main style from SideNavItem
65
+ ...getGroupTokens(getAppearance(appearance)) // control-specific tokens like icon etc,
66
+ }),
67
+ ...staticTokens.control
60
68
  });
61
69
  const controlContent = controlState => {
62
70
  const currentItemTokens = getItemTokens(getItemAppearance(controlState));
63
71
  return /*#__PURE__*/_jsx(ItemContent, {
64
- tokens: currentItemTokens,
72
+ tokens: {
73
+ ...currentItemTokens,
74
+ ...staticTokens.content
75
+ },
65
76
  children: label
66
77
  });
67
78
  };
@@ -77,9 +88,23 @@ const ItemsGroup = /*#__PURE__*/React.forwardRef((_ref, ref) => {
77
88
  active: isActive
78
89
  } // ExpandCollapse.Panel handles expanded state
79
90
  ,
91
+ disableMobileScrollBuffer: true,
80
92
  children: children
81
93
  });
82
94
  });
95
+ const staticTokens = {
96
+ panel: {
97
+ borderWidth: 0,
98
+ marginBottom: 0
99
+ },
100
+ control: {
101
+ borderWidth: 0,
102
+ textLine: null
103
+ },
104
+ content: {
105
+ accentWidth: 0
106
+ }
107
+ };
83
108
  ItemsGroup.displayName = 'ItemsGroup';
84
109
  ItemsGroup.propTypes = {
85
110
  /**
@@ -6,13 +6,28 @@ import ItemsGroup from './ItemsGroup';
6
6
  import { useThemeTokens } from '../ThemeProvider';
7
7
  import { a11yProps, componentPropType, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
8
8
  import { jsx as _jsx } from "react/jsx-runtime";
9
- function selectBorderStyles(tokens) {
9
+ const selectContainerTokens = _ref => {
10
+ let {
11
+ borderWidth,
12
+ borderStyle,
13
+ borderColor
14
+ } = _ref;
10
15
  return {
11
- borderBottomWidth: tokens.borderWidth,
12
- borderBottomStyle: tokens.borderStyle,
13
- borderBottomColor: tokens.borderColor
16
+ borderTopWidth: borderWidth,
17
+ borderStyle,
18
+ borderColor
14
19
  };
15
- }
20
+ };
21
+ const selectItemTokens = function () {
22
+ let tokens = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
23
+ let isLastItem = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
24
+ return {
25
+ ...tokens,
26
+ ...(isLastItem ? {
27
+ borderWidth: 0
28
+ } : {})
29
+ };
30
+ };
16
31
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
17
32
 
18
33
  /**
@@ -20,7 +35,7 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
20
35
  - Use in conjunction with a large amount of educational / informational content
21
36
  - Allow the user to navigate between options frequently and efficiently
22
37
  */
23
- const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
38
+ const SideNav = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
24
39
  let {
25
40
  children,
26
41
  variant = {},
@@ -29,7 +44,7 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
29
44
  itemTokens,
30
45
  groupTokens,
31
46
  ...rest
32
- } = _ref;
47
+ } = _ref2;
33
48
  const themeTokens = useThemeTokens('SideNav', tokens, variant);
34
49
  const [active, setActive] = React.useState({
35
50
  groupId: undefined,
@@ -47,14 +62,15 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
47
62
  return /*#__PURE__*/_jsx(ExpandCollapse, {
48
63
  ref: ref,
49
64
  maxOpen: accordion ? 1 : null,
50
- style: selectBorderStyles(themeTokens),
65
+ tokens: selectContainerTokens(themeTokens),
51
66
  ...selectProps(rest),
52
- children: _ref2 => {
67
+ children: _ref3 => {
53
68
  let {
54
69
  openIds,
55
70
  onToggle
56
- } = _ref2;
57
- const renderItem = (item, index, groupId) => {
71
+ } = _ref3;
72
+ const renderItem = function (item, index, groupId) {
73
+ let isLastItem = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
58
74
  const {
59
75
  itemId = `item-${index}`,
60
76
  onPress
@@ -72,7 +88,7 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
72
88
  ...variant,
73
89
  type: 'child'
74
90
  } : variant,
75
- tokens: itemTokens,
91
+ tokens: selectItemTokens(itemTokens, isLastItem),
76
92
  isActive: isItemActive(itemId, groupId),
77
93
  onPress: handlePress
78
94
  });
@@ -96,7 +112,7 @@ const SideNav = /*#__PURE__*/React.forwardRef((_ref, ref) => {
96
112
  openGroups: openIds,
97
113
  isActive: isGroupActive,
98
114
  onToggle: handleToggle
99
- }, React.Children.map(child.props.children, (item, itemIndex) => renderItem(item, itemIndex, groupId)));
115
+ }, React.Children.map(child.props.children, (item, itemIndex) => renderItem(item, itemIndex, groupId, itemIndex === child.props.children.length - 1)));
100
116
  }
101
117
  return null;
102
118
  });
package/lib/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "@gorhom/portal": "^1.0.14",
13
13
  "@react-native-picker/picker": "^2.9.0",
14
14
  "@telus-uds/system-constants": "^3.0.0",
15
- "@telus-uds/system-theme-tokens": "^4.19.0",
15
+ "@telus-uds/system-theme-tokens": "^4.20.0",
16
16
  "airbnb-prop-types": "^2.16.0",
17
17
  "css-mediaquery": "^0.1.2",
18
18
  "expo-document-picker": "^13.0.1",
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.27.0",
87
+ "version": "3.28.0",
88
88
  "types": "types/index.d.ts"
89
89
  }
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "@gorhom/portal": "^1.0.14",
13
13
  "@react-native-picker/picker": "^2.9.0",
14
14
  "@telus-uds/system-constants": "^3.0.0",
15
- "@telus-uds/system-theme-tokens": "^4.19.0",
15
+ "@telus-uds/system-theme-tokens": "^4.20.0",
16
16
  "airbnb-prop-types": "^2.16.0",
17
17
  "css-mediaquery": "^0.1.2",
18
18
  "expo-document-picker": "^13.0.1",
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.27.0",
87
+ "version": "3.28.0",
88
88
  "types": "types/index.d.ts"
89
89
  }
@@ -233,7 +233,13 @@ export const selectStyles = ({
233
233
  */
234
234
  const CardBase = React.forwardRef(
235
235
  ({ children, tokens, dataSet, backgroundImage, fullBleedContent, cardState, ...rest }, ref) => {
236
- const cardStyle = selectStyles(typeof tokens === 'function' ? tokens(cardState) : tokens)
236
+ const resolvedTokens = typeof tokens === 'function' ? tokens(cardState) : tokens
237
+ const tokensToUse =
238
+ backgroundImage && backgroundImage.src
239
+ ? { ...resolvedTokens, gradient: undefined, backgroundGradient: undefined }
240
+ : resolvedTokens
241
+
242
+ const cardStyle = selectStyles(tokensToUse)
237
243
  const props = selectProps(rest)
238
244
 
239
245
  let content = children
@@ -314,7 +320,7 @@ const CardBase = React.forwardRef(
314
320
  })
315
321
 
316
322
  return (
317
- <View style={containerStyle} dataSet={dataSet} ref={ref} {...props}>
323
+ <View style={{ ...containerStyle, borderRadius }} dataSet={dataSet} ref={ref} {...props}>
318
324
  {content}
319
325
  </View>
320
326
  )
@@ -393,7 +399,7 @@ const staticStyles = StyleSheet.create({
393
399
  contentOverlay: {
394
400
  position: 'relative',
395
401
  width: '100%',
396
- height: '100%',
402
+ minHeight: '100%',
397
403
  zIndex: 2
398
404
  },
399
405
  containContainer: {
@@ -50,7 +50,7 @@ function selectIconContainerStyles({ iconGap, iconPaddingTop, iconPosition }) {
50
50
  const paddingSide = iconPosition === 'right' ? 'paddingLeft' : 'paddingRight'
51
51
  return {
52
52
  [paddingSide]: iconGap,
53
- paddingTop: iconPaddingTop
53
+ ...(iconPaddingTop && { transform: [{ translateY: iconPaddingTop }] })
54
54
  }
55
55
  }
56
56
 
@@ -20,13 +20,14 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([
20
20
  contentfulProps
21
21
  ])
22
22
 
23
- function selectBorderStyles(tokens) {
24
- return {
25
- borderBottomWidth: tokens.borderWidth,
26
- borderBottomStyle: tokens.borderStyle,
27
- borderBottomColor: tokens.borderColor
28
- }
29
- }
23
+ const selectWrapperStyles = ({ borderWidth, borderTopWidth, borderStyle, borderColor }) => ({
24
+ borderStyle,
25
+ borderColor,
26
+ borderTopWidth,
27
+ borderBottomWidth: borderWidth,
28
+ borderBottomStyle: borderStyle,
29
+ borderBottomColor: borderColor
30
+ })
30
31
 
31
32
  /**
32
33
  * Flexible base component for lists where some or all items are collapsible headers.
@@ -55,7 +56,7 @@ const ExpandCollapse = React.forwardRef(
55
56
 
56
57
  return (
57
58
  <View style={staticStyles.container} ref={ref} {...selectProps(rest)} dataSet={dataSet}>
58
- <View style={selectBorderStyles(themeTokens)}>
59
+ <View style={selectWrapperStyles(themeTokens)}>
59
60
  {typeof children === 'function'
60
61
  ? children({ openIds, onToggle, resetValues, setValues, unsetValues, instanceId })
61
62
  : children}
@@ -96,6 +96,7 @@ const ExpandCollapsePanel = React.forwardRef(
96
96
  controlRef,
97
97
  content,
98
98
  copy = 'en',
99
+ disableMobileScrollBuffer = false,
99
100
  ...rest
100
101
  },
101
102
  ref
@@ -118,7 +119,10 @@ const ExpandCollapsePanel = React.forwardRef(
118
119
 
119
120
  // on mobile devices we require a scroll buffer equal to the font size
120
121
  // to avoid triggering scrolling unnecessarily
121
- const mobileScrollBuffer = Platform.OS === 'web' ? 0 : selectTextStyles(themeTokens)?.fontSize
122
+ const mobileScrollBuffer =
123
+ Platform.OS === 'web' || disableMobileScrollBuffer
124
+ ? 0
125
+ : selectTextStyles(themeTokens)?.fontSize
122
126
 
123
127
  const handleControlPress = (event) => {
124
128
  onToggle?.(panelId, event)
@@ -287,7 +291,11 @@ ExpandCollapsePanel.propTypes = {
287
291
  /**
288
292
  * A boolean prop to determine if the panel is a content panel or not. If true, the panel will not have a control
289
293
  */
290
- content: PropTypes.bool
294
+ content: PropTypes.bool,
295
+ /**
296
+ * A boolean prop to disable the extra scroll buffer on mobile devices (only applicable on iOS/Android, ignored on web)
297
+ */
298
+ disableMobileScrollBuffer: PropTypes.bool
291
299
  }
292
300
 
293
301
  export default ExpandCollapsePanel