@telus-uds/components-base 1.47.0 → 1.49.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 +27 -2
  2. package/component-docs.json +32 -35
  3. package/lib/Button/ButtonBase.js +6 -3
  4. package/lib/ExpandCollapse/Control.js +40 -13
  5. package/lib/ExpandCollapse/Panel.js +1 -3
  6. package/lib/List/ListItemBase.js +22 -3
  7. package/lib/SideNav/Item.js +11 -3
  8. package/lib/SideNav/ItemContent.js +2 -1
  9. package/lib/SideNav/ItemsGroup.js +11 -1
  10. package/lib/Skeleton/Skeleton.js +10 -3
  11. package/lib/Skeleton/skeleton.constant.js +2 -4
  12. package/lib/Skeleton/skeletonWebAnimation.js +13 -17
  13. package/lib/Skeleton/useSkeletonNativeAnimation.js +8 -3
  14. package/lib-module/Button/ButtonBase.js +6 -3
  15. package/lib-module/ExpandCollapse/Control.js +39 -13
  16. package/lib-module/ExpandCollapse/Panel.js +1 -3
  17. package/lib-module/List/ListItemBase.js +21 -3
  18. package/lib-module/SideNav/Item.js +10 -3
  19. package/lib-module/SideNav/ItemContent.js +2 -1
  20. package/lib-module/SideNav/ItemsGroup.js +11 -1
  21. package/lib-module/Skeleton/Skeleton.js +10 -3
  22. package/lib-module/Skeleton/skeleton.constant.js +1 -2
  23. package/lib-module/Skeleton/skeletonWebAnimation.js +14 -17
  24. package/lib-module/Skeleton/useSkeletonNativeAnimation.js +9 -4
  25. package/package.json +2 -2
  26. package/src/Button/ButtonBase.jsx +6 -2
  27. package/src/ExpandCollapse/Control.jsx +33 -27
  28. package/src/ExpandCollapse/Panel.jsx +3 -10
  29. package/src/Link/LinkBase.jsx +1 -0
  30. package/src/List/ListItemBase.jsx +18 -4
  31. package/src/SideNav/Item.jsx +8 -5
  32. package/src/SideNav/ItemContent.jsx +10 -6
  33. package/src/SideNav/ItemsGroup.jsx +10 -2
  34. package/src/SideNav/SideNav.jsx +2 -0
  35. package/src/Skeleton/Skeleton.jsx +9 -2
  36. package/src/Skeleton/skeleton.constant.js +0 -1
  37. package/src/Skeleton/skeletonWebAnimation.js +11 -11
  38. package/src/Skeleton/useSkeletonNativeAnimation.js +5 -4
  39. package/src/utils/a11y/semantics.js +7 -7
@@ -1,6 +1,7 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import Pressable from "react-native-web/dist/exports/Pressable";
3
3
  import View from "react-native-web/dist/exports/View";
4
+ import Platform from "react-native-web/dist/exports/Platform";
4
5
  import PropTypes from 'prop-types';
5
6
  import { useThemeTokensCallback, verticalAlignRow } from '../ThemeProvider';
6
7
  import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
@@ -14,25 +15,34 @@ function selectContainerStyles(_ref) {
14
15
  backgroundColor,
15
16
  borderColor,
16
17
  borderWidth,
17
- borderStyle,
18
+ borderStyle = 'solid',
18
19
  paddingLeft,
19
20
  paddingRight,
20
21
  paddingTop,
21
22
  paddingBottom,
22
23
  justifyContent,
23
24
  verticalAlign,
24
- iconPosition
25
+ iconPosition,
26
+ borderTopRightRadius,
27
+ borderBottomRightRadius,
28
+ borderTopLeftRadius,
29
+ borderBottomLeftRadius
25
30
  } = _ref;
26
31
  return {
32
+ boxSizing: 'border-box',
27
33
  backgroundColor,
28
- borderTopColor: borderColor,
29
- borderTopWidth: borderWidth,
30
- borderTopStyle: borderStyle,
34
+ borderColor,
35
+ borderWidth,
36
+ borderStyle,
31
37
  paddingLeft,
32
38
  paddingRight,
33
39
  paddingTop,
34
40
  paddingBottom,
35
41
  justifyContent,
42
+ borderTopRightRadius,
43
+ borderBottomRightRadius,
44
+ borderTopLeftRadius,
45
+ borderBottomLeftRadius,
36
46
  ...verticalAlignRow(verticalAlign, iconPosition === 'right')
37
47
  };
38
48
  } // TODO: use stack / spacer when available
@@ -51,6 +61,16 @@ function selectIconContainerStyles(_ref2) {
51
61
  };
52
62
  }
53
63
 
64
+ function selectTextContainerStyles(_ref3) {
65
+ let {
66
+ textLine
67
+ } = _ref3;
68
+ return {
69
+ textDecorationLine: textLine,
70
+ flex: 1
71
+ };
72
+ }
73
+
54
74
  function selectIconTokens(tokens) {
55
75
  return {
56
76
  color: tokens.iconColor,
@@ -58,7 +78,7 @@ function selectIconTokens(tokens) {
58
78
  };
59
79
  }
60
80
 
61
- const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref3, ref) => {
81
+ const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref4, ref) => {
62
82
  let {
63
83
  onPress,
64
84
  isExpanded,
@@ -66,10 +86,9 @@ const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref3, ref) => {
66
86
  tokens,
67
87
  accessibilityRole = 'button',
68
88
  variant,
69
- isMiniExpandCollapse = false,
70
89
  ...rest
71
- } = _ref3;
72
- const getTokens = useThemeTokensCallback(isMiniExpandCollapse ? 'ExpandCollapseMiniControl' : 'ExpandCollapseControl', tokens, variant);
90
+ } = _ref4;
91
+ const getTokens = useThemeTokensCallback('ExpandCollapseControl', tokens, variant);
73
92
  const selectedProps = selectProps({
74
93
  accessibilityRole,
75
94
  ...rest,
@@ -78,12 +97,12 @@ const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref3, ref) => {
78
97
  }
79
98
  });
80
99
 
81
- const getControlState = _ref4 => {
100
+ const getControlState = _ref5 => {
82
101
  let {
83
102
  pressed,
84
103
  hovered,
85
104
  focused
86
- } = _ref4;
105
+ } = _ref5;
87
106
  return {
88
107
  pressed,
89
108
  hover: hovered,
@@ -94,7 +113,11 @@ const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref3, ref) => {
94
113
 
95
114
  const getControlTokens = pressableState => getTokens(getControlState(pressableState));
96
115
 
97
- const getPressableStyle = pressableState => selectContainerStyles(getControlTokens(pressableState));
116
+ const getPressableStyle = pressableState => ({ ...selectContainerStyles(getControlTokens(pressableState)),
117
+ ...(Platform.OS === 'web' ? {
118
+ outline: 'none'
119
+ } : {})
120
+ });
98
121
 
99
122
  return /*#__PURE__*/_jsx(Pressable, {
100
123
  ref: ref,
@@ -111,7 +134,10 @@ const ExpandCollapseControl = /*#__PURE__*/forwardRef((_ref3, ref) => {
111
134
  style: selectIconContainerStyles(themeTokens),
112
135
  children: /*#__PURE__*/_jsx(IconComponent, { ...selectIconTokens(themeTokens)
113
136
  })
114
- }), typeof children === 'function' ? children(getControlState(pressableState)) : children]
137
+ }), /*#__PURE__*/_jsx(View, {
138
+ style: selectTextContainerStyles(themeTokens),
139
+ children: typeof children === 'function' ? children(getControlState(pressableState)) : children
140
+ })]
115
141
  });
116
142
  }
117
143
  });
@@ -48,7 +48,6 @@ const ExpandCollapsePanel = /*#__PURE__*/forwardRef((_ref2, ref) => {
48
48
  children,
49
49
  tokens,
50
50
  variant,
51
- isMiniExpandCollapse = false,
52
51
  controlRef,
53
52
  ...rest
54
53
  } = _ref2;
@@ -59,7 +58,7 @@ const ExpandCollapsePanel = /*#__PURE__*/forwardRef((_ref2, ref) => {
59
58
  expanded: isExpanded
60
59
  }
61
60
  });
62
- const themeTokens = useThemeTokens(isMiniExpandCollapse ? 'ExpandCollapseMiniPanel' : 'ExpandCollapsePanel', tokens, variant, {
61
+ const themeTokens = useThemeTokens('ExpandCollapsePanel', tokens, variant, {
63
62
  expanded: isExpanded
64
63
  });
65
64
 
@@ -95,7 +94,6 @@ const ExpandCollapsePanel = /*#__PURE__*/forwardRef((_ref2, ref) => {
95
94
  variant: variant,
96
95
  onPress: handleControlPress,
97
96
  ref: controlRef,
98
- isMiniExpandCollapse: isMiniExpandCollapse,
99
97
  children: control
100
98
  }), isExpanded && /*#__PURE__*/_jsx(View, {
101
99
  style: {
@@ -7,6 +7,7 @@ import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps
7
7
  import ListItemContent from './ListItemContent';
8
8
  import ListItemMark from './ListItemMark';
9
9
  import Typography from '../Typography';
10
+ import { useThemeTokens } from '../ThemeProvider';
10
11
  import { jsx as _jsx } from "react/jsx-runtime";
11
12
  import { jsxs as _jsxs } from "react/jsx-runtime";
12
13
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
@@ -57,12 +58,29 @@ const ListItemBase = /*#__PURE__*/forwardRef((_ref3, ref) => {
57
58
  const themeTokens = typeof tokens === 'function' ? tokens() : tokens;
58
59
  const itemBlockStyles = selectItemBlockStyles(themeTokens);
59
60
  const dividerStyles = selectDividerStyles(themeTokens);
61
+ const {
62
+ iconMarginTop,
63
+ itemIconSize
64
+ } = themeTokens;
65
+ let adjustedIconMarginTop = iconMarginTop;
66
+ const {
67
+ fontSize,
68
+ lineHeight: lineHeightRatio
69
+ } = useThemeTokens('Typography', {}, {
70
+ size: 'h4',
71
+ bold: true
72
+ });
73
+
74
+ if (title) {
75
+ adjustedIconMarginTop = (fontSize * lineHeightRatio - itemIconSize) / 2;
76
+ }
60
77
  /**
61
78
  * Function responsible returning styling, in case the item is the last shouldn't
62
79
  * add extra margin on the bottom, if "showDivider" is true it should add a divider
63
80
  * and custom margin and padding, otherwise just adds a margin to the bottom
64
81
  */
65
82
 
83
+
66
84
  const getContainerStyle = () => {
67
85
  if (isLastItem) {
68
86
  return undefined;
@@ -90,11 +108,11 @@ const ListItemBase = /*#__PURE__*/forwardRef((_ref3, ref) => {
90
108
  style: [{
91
109
  flex: 1,
92
110
  flexDirection: 'row'
93
- }, !title && {
94
- alignItems: 'center'
95
111
  }],
96
112
  children: [/*#__PURE__*/_jsx(ListItemMark, {
97
- tokens: tokens,
113
+ tokens: { ...tokens,
114
+ iconMarginTop: adjustedIconMarginTop
115
+ },
98
116
  icon: icon,
99
117
  iconColor: iconColor,
100
118
  iconSize: iconSize
@@ -1,5 +1,6 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import Pressable from "react-native-web/dist/exports/Pressable";
3
+ import Platform from "react-native-web/dist/exports/Platform";
3
4
  import PropTypes from 'prop-types';
4
5
  import { a11yProps, getTokensPropType, hrefAttrsProp, linkProps, selectSystemProps, variantProp, viewProps } from '../utils';
5
6
  import { useThemeTokensCallback, verticalAlignRow } from '../ThemeProvider';
@@ -73,16 +74,22 @@ const Item = /*#__PURE__*/forwardRef((_ref2, ref) => {
73
74
 
74
75
  const getAppearanceState = _ref3 => {
75
76
  let {
76
- hovered
77
+ hovered,
78
+ focused
77
79
  } = _ref3;
78
80
  return {
79
81
  hover: hovered,
80
82
  active: isActive,
81
- expanded: isExpanded
83
+ expanded: isExpanded,
84
+ focus: focused
82
85
  };
83
86
  };
84
87
 
85
- const getPressableStyle = pressableState => selectItemStyles(getTokens(getAppearanceState(pressableState)));
88
+ const getPressableStyle = pressableState => ({ ...selectItemStyles(getTokens(getAppearanceState(pressableState))),
89
+ ...(Platform.OS === 'web' ? {
90
+ outline: 'none'
91
+ } : {})
92
+ });
86
93
 
87
94
  return /*#__PURE__*/_jsx(Pressable, {
88
95
  ref: ref,
@@ -26,9 +26,10 @@ const ItemContent = _ref => {
26
26
  children,
27
27
  tokens
28
28
  } = _ref;
29
+ const typographyTokens = selectTokens('Typography', tokens);
29
30
  return /*#__PURE__*/_jsxs(_Fragment, {
30
31
  children: [/*#__PURE__*/_jsx(Typography, {
31
- tokens: selectTokens('Typography', tokens),
32
+ tokens: typographyTokens,
32
33
  children: children
33
34
  }), /*#__PURE__*/_jsx(View, {
34
35
  style: [staticStyles.absolute, selectAccentStyles(tokens)]
@@ -42,7 +42,17 @@ const ItemsGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
42
42
 
43
43
  const getGroupTokens = useThemeTokensCallback('SideNavItemsGroup', tokens, variant);
44
44
 
45
- const getPanelTokens = appearance => selectTokens('ExpandCollapsePanel', getGroupTokens(getAppearance(appearance)));
45
+ const getPanelTokens = appearance => {
46
+ const {
47
+ panelBorderColor,
48
+ ...itemsGroupTokens
49
+ } = getGroupTokens(getAppearance(appearance));
50
+ const groupTokens = { ...itemsGroupTokens,
51
+ borderWidth: 0,
52
+ marginBottom: 0
53
+ };
54
+ return selectTokens('ExpandCollapsePanel', groupTokens);
55
+ };
46
56
 
47
57
  const getItemTokens = useThemeTokensCallback('SideNavItem', itemTokens, variant);
48
58
 
@@ -75,11 +75,18 @@ const Skeleton = /*#__PURE__*/forwardRef((_ref5, ref) => {
75
75
  }
76
76
  } : // Size by an index on the spacing scale (getting default index from theme if none provided)
77
77
  sizeIndex || themeTokens.size;
78
- const skeletonHeight = useSpacingScale(spacingScaleValue);
79
- const nativeAnimation = useSkeletonNativeAnimation();
78
+ const skeletonHeight = useSpacingScale(spacingScaleValue); // Animation color and animation duration
79
+
80
+ const {
81
+ secondColor,
82
+ animationDuration
83
+ } = themeTokens;
84
+ const nativeAnimation = useSkeletonNativeAnimation({
85
+ animationDuration
86
+ });
80
87
 
81
88
  const getAnimationBasedOnPlatform = () => {
82
- const animation = Platform.OS === 'web' ? skeletonWebAnimation : nativeAnimation; // We must pass the animation styles through `StyleSheet.create`
89
+ const animation = Platform.OS === 'web' ? skeletonWebAnimation(secondColor, animationDuration) : nativeAnimation; // We must pass the animation styles through `StyleSheet.create`
83
90
  // @see https://github.com/necolas/react-native-web/issues/2387
84
91
 
85
92
  const styles = StyleSheet.create({
@@ -1,3 +1,2 @@
1
1
  export const DEFAULT_OPACITY = 1;
2
- export const OPACITY_STOP = 0.4;
3
- export const ANIMATION_DURATION = 1500;
2
+ export const OPACITY_STOP = 0.4;
@@ -1,18 +1,15 @@
1
- import { ANIMATION_DURATION, DEFAULT_OPACITY, OPACITY_STOP } from './skeleton.constant';
2
- export default {
3
- animationDuration: `${ANIMATION_DURATION}ms`,
4
- animationTimingFunction: 'ease-in-out',
5
- animationDelay: '0.5s',
6
- animationIterationCount: 'infinite',
7
- animationKeyframes: {
8
- '0%': {
9
- opacity: DEFAULT_OPACITY
10
- },
11
- '50%': {
12
- opacity: OPACITY_STOP
13
- },
14
- '100%': {
15
- opacity: DEFAULT_OPACITY
1
+ const skeletonWebAnimation = (secondColor, animationTime) => {
2
+ return {
3
+ animationDuration: `${animationTime}ms`,
4
+ animationTimingFunction: 'ease-in-out',
5
+ animationDelay: '0.5s',
6
+ animationIterationCount: 'infinite',
7
+ animationKeyframes: {
8
+ '50%': {
9
+ backgroundColor: secondColor
10
+ }
16
11
  }
17
- }
18
- };
12
+ };
13
+ };
14
+
15
+ export default skeletonWebAnimation;
@@ -1,18 +1,23 @@
1
1
  import { useEffect, useRef } from 'react';
2
2
  import Animated from "react-native-web/dist/exports/Animated";
3
3
  import Platform from "react-native-web/dist/exports/Platform";
4
- import { ANIMATION_DURATION, DEFAULT_OPACITY, OPACITY_STOP } from './skeleton.constant';
4
+ import { DEFAULT_OPACITY, OPACITY_STOP } from './skeleton.constant';
5
5
 
6
- const useSkeletonNativeAnimation = () => {
6
+ const useSkeletonNativeAnimation = _ref => {
7
+ let {
8
+ animationDuration
9
+ } = _ref;
7
10
  const fadeAnimation = useRef(new Animated.Value(DEFAULT_OPACITY)).current;
11
+ /* eslint-disable react-hooks/exhaustive-deps */
12
+
8
13
  useEffect(() => {
9
14
  const fade = Animated.sequence([Animated.timing(fadeAnimation, {
10
15
  toValue: OPACITY_STOP,
11
- duration: ANIMATION_DURATION,
16
+ duration: animationDuration,
12
17
  useNativeDriver: Platform.OS !== 'web'
13
18
  }), Animated.timing(fadeAnimation, {
14
19
  toValue: DEFAULT_OPACITY,
15
- duration: ANIMATION_DURATION,
20
+ duration: animationDuration,
16
21
  useNativeDriver: Platform.OS !== 'web'
17
22
  })]);
18
23
  Animated.loop(fade).start();
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "@floating-ui/react-native": "^0.8.1",
12
12
  "@gorhom/portal": "^1.0.14",
13
13
  "@telus-uds/system-constants": "^1.2.1",
14
- "@telus-uds/system-theme-tokens": "^2.29.0",
14
+ "@telus-uds/system-theme-tokens": "^2.31.0",
15
15
  "airbnb-prop-types": "^2.16.0",
16
16
  "lodash.debounce": "^4.0.8",
17
17
  "lodash.merge": "^4.6.2",
@@ -72,5 +72,5 @@
72
72
  "standard-engine": {
73
73
  "skip": true
74
74
  },
75
- "version": "1.47.0"
75
+ "version": "1.49.0"
76
76
  }
@@ -30,7 +30,6 @@ const getOuterBorderOffset = ({ outerBorderGap = 0, outerBorderWidth = 0 }) =>
30
30
  outerBorderGap + outerBorderWidth
31
31
 
32
32
  const selectOuterContainerStyles = ({
33
- alignSelf,
34
33
  opacity,
35
34
  outerBorderColor,
36
35
  outerBorderWidth,
@@ -38,7 +37,11 @@ const selectOuterContainerStyles = ({
38
37
  borderRadius,
39
38
  outerBackgroundColor
40
39
  }) => ({
41
- alignSelf,
40
+ ...Platform.select({
41
+ native: {
42
+ alignSelf: 'flex-start'
43
+ }
44
+ }),
42
45
  backgroundColor: outerBackgroundColor,
43
46
  opacity,
44
47
  ...applyOuterBorder({
@@ -162,6 +165,7 @@ const selectWebOnlyStyles = (inactive, themeTokens, { accessibilityRole }) => {
162
165
  web: {
163
166
  // if it would overflow the container, wraps instead
164
167
  maxWidth: `calc(100% + ${getOuterBorderOffset(themeTokens) * 2}px)`,
168
+ width: 'fit-content',
165
169
  outline: 'none', // removes the default browser :focus outline
166
170
  ...getCursorStyle(inactive, accessibilityRole)
167
171
  },
@@ -1,5 +1,5 @@
1
1
  import React, { forwardRef } from 'react'
2
- import { Pressable, View } from 'react-native'
2
+ import { Pressable, View, Platform } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
4
 
5
5
  import { useThemeTokensCallback, verticalAlignRow } from '../ThemeProvider'
@@ -11,25 +11,34 @@ function selectContainerStyles({
11
11
  backgroundColor,
12
12
  borderColor,
13
13
  borderWidth,
14
- borderStyle,
14
+ borderStyle = 'solid',
15
15
  paddingLeft,
16
16
  paddingRight,
17
17
  paddingTop,
18
18
  paddingBottom,
19
19
  justifyContent,
20
20
  verticalAlign,
21
- iconPosition
21
+ iconPosition,
22
+ borderTopRightRadius,
23
+ borderBottomRightRadius,
24
+ borderTopLeftRadius,
25
+ borderBottomLeftRadius
22
26
  }) {
23
27
  return {
28
+ boxSizing: 'border-box',
24
29
  backgroundColor,
25
- borderTopColor: borderColor,
26
- borderTopWidth: borderWidth,
27
- borderTopStyle: borderStyle,
30
+ borderColor,
31
+ borderWidth,
32
+ borderStyle,
28
33
  paddingLeft,
29
34
  paddingRight,
30
35
  paddingTop,
31
36
  paddingBottom,
32
37
  justifyContent,
38
+ borderTopRightRadius,
39
+ borderBottomRightRadius,
40
+ borderTopLeftRadius,
41
+ borderBottomLeftRadius,
33
42
  ...verticalAlignRow(verticalAlign, iconPosition === 'right')
34
43
  }
35
44
  }
@@ -43,6 +52,13 @@ function selectIconContainerStyles({ iconGap, iconPaddingTop, iconPosition }) {
43
52
  }
44
53
  }
45
54
 
55
+ function selectTextContainerStyles({ textLine }) {
56
+ return {
57
+ textDecorationLine: textLine,
58
+ flex: 1
59
+ }
60
+ }
61
+
46
62
  function selectIconTokens(tokens) {
47
63
  return {
48
64
  color: tokens.iconColor,
@@ -52,23 +68,10 @@ function selectIconTokens(tokens) {
52
68
 
53
69
  const ExpandCollapseControl = forwardRef(
54
70
  (
55
- {
56
- onPress,
57
- isExpanded,
58
- children,
59
- tokens,
60
- accessibilityRole = 'button',
61
- variant,
62
- isMiniExpandCollapse = false,
63
- ...rest
64
- },
71
+ { onPress, isExpanded, children, tokens, accessibilityRole = 'button', variant, ...rest },
65
72
  ref
66
73
  ) => {
67
- const getTokens = useThemeTokensCallback(
68
- isMiniExpandCollapse ? 'ExpandCollapseMiniControl' : 'ExpandCollapseControl',
69
- tokens,
70
- variant
71
- )
74
+ const getTokens = useThemeTokensCallback('ExpandCollapseControl', tokens, variant)
72
75
 
73
76
  const selectedProps = selectProps({
74
77
  accessibilityRole,
@@ -86,14 +89,15 @@ const ExpandCollapseControl = forwardRef(
86
89
  expanded: isExpanded
87
90
  })
88
91
  const getControlTokens = (pressableState) => getTokens(getControlState(pressableState))
89
- const getPressableStyle = (pressableState) =>
90
- selectContainerStyles(getControlTokens(pressableState))
92
+ const getPressableStyle = (pressableState) => ({
93
+ ...selectContainerStyles(getControlTokens(pressableState)),
94
+ ...(Platform.OS === 'web' ? { outline: 'none' } : {})
95
+ })
91
96
 
92
97
  return (
93
98
  <Pressable ref={ref} {...selectedProps} onPress={onPress} style={getPressableStyle}>
94
99
  {(pressableState) => {
95
100
  const { icon: IconComponent, ...themeTokens } = getControlTokens(pressableState)
96
-
97
101
  return (
98
102
  <>
99
103
  {IconComponent && (
@@ -101,9 +105,11 @@ const ExpandCollapseControl = forwardRef(
101
105
  <IconComponent {...selectIconTokens(themeTokens)} />
102
106
  </View>
103
107
  )}
104
- {typeof children === 'function'
105
- ? children(getControlState(pressableState))
106
- : children}
108
+ <View style={selectTextContainerStyles(themeTokens)}>
109
+ {typeof children === 'function'
110
+ ? children(getControlState(pressableState))
111
+ : children}
112
+ </View>
107
113
  </>
108
114
  )
109
115
  }}
@@ -51,7 +51,6 @@ const ExpandCollapsePanel = forwardRef(
51
51
  children,
52
52
  tokens,
53
53
  variant,
54
- isMiniExpandCollapse = false,
55
54
  controlRef,
56
55
  ...rest
57
56
  },
@@ -68,14 +67,9 @@ const ExpandCollapsePanel = forwardRef(
68
67
  }
69
68
  })
70
69
 
71
- const themeTokens = useThemeTokens(
72
- isMiniExpandCollapse ? 'ExpandCollapseMiniPanel' : 'ExpandCollapsePanel',
73
- tokens,
74
- variant,
75
- {
76
- expanded: isExpanded
77
- }
78
- )
70
+ const themeTokens = useThemeTokens('ExpandCollapsePanel', tokens, variant, {
71
+ expanded: isExpanded
72
+ })
79
73
 
80
74
  const handleControlPress = (event) => {
81
75
  onToggle(panelId, event)
@@ -106,7 +100,6 @@ const ExpandCollapsePanel = forwardRef(
106
100
  variant={variant}
107
101
  onPress={handleControlPress}
108
102
  ref={controlRef}
109
- isMiniExpandCollapse={isMiniExpandCollapse}
110
103
  >
111
104
  {control}
112
105
  </ExpandCollapseControl>
@@ -126,6 +126,7 @@ const LinkBase = forwardRef(
126
126
  ) => {
127
127
  const { onPress, ...props } = clickProps.toPressProps(rawRest)
128
128
  const { hrefAttrs, rest } = hrefAttrsProp.bundle(props)
129
+
129
130
  const selectedProps = selectProps({
130
131
  accessibilityRole,
131
132
  href,
@@ -6,6 +6,7 @@ import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps
6
6
  import ListItemContent from './ListItemContent'
7
7
  import ListItemMark from './ListItemMark'
8
8
  import Typography from '../Typography'
9
+ import { useThemeTokens } from '../ThemeProvider'
9
10
 
10
11
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
11
12
 
@@ -43,7 +44,16 @@ const ListItemBase = forwardRef(
43
44
 
44
45
  const itemBlockStyles = selectItemBlockStyles(themeTokens)
45
46
  const dividerStyles = selectDividerStyles(themeTokens)
46
-
47
+ const { iconMarginTop, itemIconSize } = themeTokens
48
+ let adjustedIconMarginTop = iconMarginTop
49
+ const { fontSize, lineHeight: lineHeightRatio } = useThemeTokens(
50
+ 'Typography',
51
+ {},
52
+ { size: 'h4', bold: true }
53
+ )
54
+ if (title) {
55
+ adjustedIconMarginTop = (fontSize * lineHeightRatio - itemIconSize) / 2
56
+ }
47
57
  /**
48
58
  * Function responsible returning styling, in case the item is the last shouldn't
49
59
  * add extra margin on the bottom, if "showDivider" is true it should add a divider
@@ -76,11 +86,15 @@ const ListItemBase = forwardRef(
76
86
  {
77
87
  flex: 1,
78
88
  flexDirection: 'row'
79
- },
80
- !title && { alignItems: 'center' }
89
+ }
81
90
  ]}
82
91
  >
83
- <ListItemMark tokens={tokens} icon={icon} iconColor={iconColor} iconSize={iconSize} />
92
+ <ListItemMark
93
+ tokens={{ ...tokens, iconMarginTop: adjustedIconMarginTop }}
94
+ icon={icon}
95
+ iconColor={iconColor}
96
+ iconSize={iconSize}
97
+ />
84
98
  <View style={staticStyles.titleAndContentContainer}>
85
99
  {Boolean(title) && (
86
100
  <Typography variant={{ size: 'h4', bold: true }}>{title}</Typography>
@@ -1,5 +1,5 @@
1
1
  import React, { forwardRef } from 'react'
2
- import { Pressable } from 'react-native'
2
+ import { Pressable, Platform } from 'react-native'
3
3
  import PropTypes from 'prop-types'
4
4
  import {
5
5
  a11yProps,
@@ -76,13 +76,16 @@ const Item = forwardRef(
76
76
  })
77
77
 
78
78
  const getTokens = useThemeTokensCallback('SideNavItem', tokens, variant)
79
- const getAppearanceState = ({ hovered }) => ({
79
+ const getAppearanceState = ({ hovered, focused }) => ({
80
80
  hover: hovered,
81
81
  active: isActive,
82
- expanded: isExpanded
82
+ expanded: isExpanded,
83
+ focus: focused
84
+ })
85
+ const getPressableStyle = (pressableState) => ({
86
+ ...selectItemStyles(getTokens(getAppearanceState(pressableState))),
87
+ ...(Platform.OS === 'web' ? { outline: 'none' } : {})
83
88
  })
84
- const getPressableStyle = (pressableState) =>
85
- selectItemStyles(getTokens(getAppearanceState(pressableState)))
86
89
 
87
90
  return (
88
91
  <Pressable
@@ -19,12 +19,16 @@ export function selectAccentStyles(tokens) {
19
19
  /**
20
20
  * Content inside an item or control in a SideNav, themed by the SideNavItem theme
21
21
  */
22
- const ItemContent = ({ children, tokens }) => (
23
- <>
24
- <Typography tokens={selectTokens('Typography', tokens)}>{children}</Typography>
25
- <View style={[staticStyles.absolute, selectAccentStyles(tokens)]} />
26
- </>
27
- )
22
+ const ItemContent = ({ children, tokens }) => {
23
+ const typographyTokens = selectTokens('Typography', tokens)
24
+
25
+ return (
26
+ <>
27
+ <Typography tokens={typographyTokens}>{children}</Typography>
28
+ <View style={[staticStyles.absolute, selectAccentStyles(tokens)]} />
29
+ </>
30
+ )
31
+ }
28
32
 
29
33
  ItemContent.propTypes = {
30
34
  tokens: getTokensPropType('SideNavItem'),