@telus-uds/components-base 1.21.0 → 1.23.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 (42) hide show
  1. package/CHANGELOG.md +30 -2
  2. package/component-docs.json +470 -1
  3. package/lib/Button/ButtonGroup.js +9 -0
  4. package/lib/Checkbox/CheckboxGroup.js +2 -0
  5. package/lib/ExpandCollapse/Control.js +3 -1
  6. package/lib/Feedback/Feedback.js +5 -2
  7. package/lib/Fieldset/Fieldset.js +42 -13
  8. package/lib/Fieldset/FieldsetContainer.js +9 -3
  9. package/lib/List/PressableListItemBase.js +1 -0
  10. package/lib/QuickLinksFeature/QuickLinksFeature.js +91 -0
  11. package/lib/QuickLinksFeature/QuickLinksFeatureItem.js +157 -0
  12. package/lib/QuickLinksFeature/index.js +16 -0
  13. package/lib/Radio/RadioGroup.js +5 -1
  14. package/lib/RadioCard/RadioCardGroup.js +2 -0
  15. package/lib/index.js +9 -0
  16. package/lib-module/Button/ButtonGroup.js +9 -0
  17. package/lib-module/Checkbox/CheckboxGroup.js +2 -0
  18. package/lib-module/ExpandCollapse/Control.js +3 -1
  19. package/lib-module/Feedback/Feedback.js +5 -2
  20. package/lib-module/Fieldset/Fieldset.js +39 -12
  21. package/lib-module/Fieldset/FieldsetContainer.js +9 -3
  22. package/lib-module/List/PressableListItemBase.js +1 -0
  23. package/lib-module/QuickLinksFeature/QuickLinksFeature.js +69 -0
  24. package/lib-module/QuickLinksFeature/QuickLinksFeatureItem.js +130 -0
  25. package/lib-module/QuickLinksFeature/index.js +4 -0
  26. package/lib-module/Radio/RadioGroup.js +5 -1
  27. package/lib-module/RadioCard/RadioCardGroup.js +2 -0
  28. package/lib-module/index.js +1 -0
  29. package/package.json +2 -2
  30. package/src/Button/ButtonGroup.jsx +10 -0
  31. package/src/Checkbox/CheckboxGroup.jsx +2 -0
  32. package/src/ExpandCollapse/Control.jsx +3 -2
  33. package/src/Feedback/Feedback.jsx +11 -3
  34. package/src/Fieldset/Fieldset.jsx +45 -13
  35. package/src/Fieldset/FieldsetContainer.jsx +29 -12
  36. package/src/List/PressableListItemBase.jsx +1 -0
  37. package/src/QuickLinksFeature/QuickLinksFeature.jsx +65 -0
  38. package/src/QuickLinksFeature/QuickLinksFeatureItem.jsx +114 -0
  39. package/src/QuickLinksFeature/index.js +6 -0
  40. package/src/Radio/RadioGroup.jsx +5 -3
  41. package/src/RadioCard/RadioCardGroup.jsx +2 -0
  42. package/src/index.js +1 -0
@@ -11,12 +11,16 @@ const FieldsetContainer = /*#__PURE__*/forwardRef((_ref, ref) => {
11
11
  children,
12
12
  inactive,
13
13
  accessibilityRole,
14
- name: fieldsetName
14
+ name: fieldsetName,
15
+ showBorderStyle = false,
16
+ borderStyle
15
17
  } = _ref;
18
+ // If needs border for error design or reset the component style
19
+ const styleContainer = showBorderStyle ? borderStyle : cssReset;
16
20
  return /*#__PURE__*/_jsx("fieldset", {
17
21
  ref: ref,
18
22
  disabled: inactive,
19
- style: cssReset,
23
+ style: styleContainer,
20
24
  role: accessibilityRole,
21
25
  name: fieldsetName,
22
26
  children: children
@@ -27,6 +31,8 @@ FieldsetContainer.propTypes = {
27
31
  accessibilityRole: PropTypes.string,
28
32
  children: PropTypes.node,
29
33
  inactive: PropTypes.bool,
30
- name: PropTypes.string
34
+ name: PropTypes.string,
35
+ showBorderStyle: PropTypes.bool,
36
+ borderStyle: PropTypes.object
31
37
  };
32
38
  export default FieldsetContainer;
@@ -105,6 +105,7 @@ const staticStyles = StyleSheet.create({
105
105
  PressableListItemBase.propTypes = { ...withLinkRouter.propTypes,
106
106
  href: PropTypes.string,
107
107
  onPress: PropTypes.func,
108
+ // eslint-disable-next-line react/forbid-prop-types
108
109
  tokens: PropTypes.any,
109
110
  icon: PropTypes.elementType,
110
111
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
@@ -0,0 +1,69 @@
1
+ import React, { forwardRef, Children, cloneElement } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { StackWrap } from '../StackView';
4
+ import { useThemeTokens } from '../ThemeProvider';
5
+ import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'; // pass through and type relevant system props - add more sets for interactive components
6
+
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
9
+
10
+ const isQuickListItem = element => {
11
+ var _element$type, _element$type2;
12
+
13
+ const elementName = (element === null || element === void 0 ? void 0 : (_element$type = element.type) === null || _element$type === void 0 ? void 0 : _element$type.displayName) || (element === null || element === void 0 ? void 0 : (_element$type2 = element.type) === null || _element$type2 === void 0 ? void 0 : _element$type2.name);
14
+ return Boolean(elementName.match(/QuickLinksFeatureItem/));
15
+ };
16
+ /**
17
+ * QuickLinksFeature renders a list of interactive items.
18
+ * - This is the base component that is used as a wrapper and accepts a List of `QuickLinksFeature.Item`
19
+ */
20
+
21
+
22
+ const QuickLinksFeature = /*#__PURE__*/forwardRef((_ref, ref) => {
23
+ let {
24
+ tokens,
25
+ variant,
26
+ tag = 'ul',
27
+ children,
28
+ ...rest
29
+ } = _ref;
30
+ const {
31
+ stackGap,
32
+ stackJustify,
33
+ stackSpace
34
+ } = useThemeTokens('QuickLinksFeature', tokens, variant);
35
+ const items = Children.map(children, child => {
36
+ if (isQuickListItem(child)) {
37
+ return /*#__PURE__*/cloneElement(child, child.props);
38
+ }
39
+
40
+ return null;
41
+ });
42
+ return /*#__PURE__*/_jsx(StackWrap, {
43
+ space: stackSpace,
44
+ gap: stackGap,
45
+ tokens: {
46
+ justifyContent: stackJustify
47
+ },
48
+ tag: tag,
49
+ ref: ref,
50
+ ...selectProps(rest),
51
+ children: items
52
+ });
53
+ });
54
+ QuickLinksFeature.displayName = 'QuickLinksFeature';
55
+ QuickLinksFeature.propTypes = { ...selectedSystemPropTypes,
56
+ tokens: getTokensPropType('QuickLinksFeature'),
57
+ variant: variantProp.propType,
58
+
59
+ /**
60
+ * Default wrapper tag, by default it's "ul"
61
+ */
62
+ tag: PropTypes.string,
63
+
64
+ /**
65
+ * QuickLinksFeature.Item component
66
+ */
67
+ children: PropTypes.node
68
+ };
69
+ export default QuickLinksFeature;
@@ -0,0 +1,130 @@
1
+ import React, { forwardRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Image from "react-native-web/dist/exports/Image";
4
+ import Platform from "react-native-web/dist/exports/Platform";
5
+ import Text from "react-native-web/dist/exports/Text";
6
+ import View from "react-native-web/dist/exports/View";
7
+ import { getTokensPropType, variantProp, withLinkRouter, a11yProps, linkProps, selectSystemProps } from '../utils';
8
+ import { useViewport } from '../ViewportProvider';
9
+ import { useThemeTokensCallback } from '../ThemeProvider';
10
+ import { Link } from '../Link';
11
+ import { StackWrap } from '../StackView'; // pass through and type relevant system props - add more sets for interactive components
12
+
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ import { jsxs as _jsxs } from "react/jsx-runtime";
15
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps]);
16
+
17
+ const selectImageStyle = imageDimension => ({
18
+ width: imageDimension,
19
+ height: imageDimension,
20
+ ...Platform.select({
21
+ // TODO: https://github.com/telus/universal-design-system/issues/487
22
+ web: {
23
+ transition: 'width 200ms, height 200ms'
24
+ }
25
+ })
26
+ });
27
+
28
+ const selectContainerStyle = _ref => {
29
+ let {
30
+ contentMaxDimension,
31
+ textAlign
32
+ } = _ref;
33
+ return {
34
+ textAlign,
35
+ width: contentMaxDimension,
36
+ overflow: 'hidden'
37
+ };
38
+ };
39
+
40
+ const selectImageContainerStyle = contentMaxDimension => ({
41
+ width: contentMaxDimension,
42
+ height: contentMaxDimension,
43
+ justifyContent: 'center',
44
+ alignItems: 'center'
45
+ });
46
+ /**
47
+ * Component export along with QuickLinksFeature to be used as children
48
+ *
49
+ * It will receive a image source and a accessibility label and will render a link accordingly with the theme tokens
50
+ */
51
+
52
+
53
+ const QuickLinksFeatureItem = /*#__PURE__*/forwardRef((_ref2, ref) => {
54
+ let {
55
+ tokens,
56
+ variant,
57
+ children,
58
+ imageAccessibilityLabel,
59
+ imageSource,
60
+ ...rest
61
+ } = _ref2;
62
+ const viewport = useViewport();
63
+ const getTokens = useThemeTokensCallback('QuickLinksFeatureItem', tokens, variant);
64
+ const [hover, setHover] = useState(false);
65
+ const {
66
+ contentDirection,
67
+ contentSpace,
68
+ contentAlignItems,
69
+ contentMaxDimension,
70
+ imageDimension,
71
+ textAlign
72
+ } = getTokens({
73
+ viewport,
74
+ hover
75
+ });
76
+ return /*#__PURE__*/_jsx(Link, {
77
+ ref: ref,
78
+ tokens: state => {
79
+ setHover(state.hover);
80
+ return getTokens(state);
81
+ },
82
+ ...selectProps(rest),
83
+ children: /*#__PURE__*/_jsx(View, {
84
+ style: selectContainerStyle({
85
+ contentMaxDimension,
86
+ textAlign
87
+ }),
88
+ children: /*#__PURE__*/_jsxs(StackWrap, {
89
+ direction: contentDirection,
90
+ space: contentSpace,
91
+ tokens: {
92
+ alignItems: contentAlignItems
93
+ },
94
+ children: [/*#__PURE__*/_jsx(View, {
95
+ style: selectImageContainerStyle(contentMaxDimension),
96
+ children: /*#__PURE__*/_jsx(Image, {
97
+ accessibilityIgnoresInvertColors: true,
98
+ imageAccessibilityLabel: imageAccessibilityLabel,
99
+ source: imageSource,
100
+ style: selectImageStyle(imageDimension)
101
+ })
102
+ }), /*#__PURE__*/_jsx(Text, {
103
+ children: children
104
+ })]
105
+ })
106
+ })
107
+ });
108
+ });
109
+ QuickLinksFeatureItem.displayName = 'QuickLinksFeatureItem';
110
+ QuickLinksFeatureItem.propTypes = { ...withLinkRouter.propTypes,
111
+ ...selectedSystemPropTypes,
112
+ tokens: getTokensPropType('QuickLinksFeatureItem'),
113
+ variant: variantProp.propType,
114
+
115
+ /**
116
+ * Text which will be rendered within the Link
117
+ */
118
+ children: PropTypes.node.isRequired,
119
+
120
+ /**
121
+ * Image accessibility label
122
+ */
123
+ imageAccessibilityLabel: PropTypes.string.isRequired,
124
+
125
+ /**
126
+ * Image node or Image url
127
+ */
128
+ imageSource: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired
129
+ };
130
+ export default withLinkRouter(QuickLinksFeatureItem);
@@ -0,0 +1,4 @@
1
+ import QuickLinksFeature from './QuickLinksFeature';
2
+ import QuickLinksFeatureItem from './QuickLinksFeatureItem';
3
+ QuickLinksFeature.Item = QuickLinksFeatureItem;
4
+ export default QuickLinksFeature;
@@ -108,6 +108,7 @@ const RadioGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
108
108
  id,
109
109
  onChange: itemOnChange,
110
110
  ref: itemRef,
111
+ description,
111
112
  ...itemRest
112
113
  } = _ref2;
113
114
  const radioId = id || "Radio[".concat(index, "]");
@@ -119,7 +120,6 @@ const RadioGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
119
120
  };
120
121
 
121
122
  return /*#__PURE__*/_jsx(Radio, {
122
- error: validation === 'error',
123
123
  ref: itemRef,
124
124
  id: radioId,
125
125
  checked: isChecked,
@@ -129,6 +129,7 @@ const RadioGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
129
129
  name: inputGroupName,
130
130
  tokens: radioTokens,
131
131
  variant: variant,
132
+ description: description,
132
133
  ...selectItemProps(itemRest)
133
134
  }, radioId);
134
135
  });
@@ -144,6 +145,8 @@ const RadioGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
144
145
  feedback: feedback,
145
146
  inactive: inactive,
146
147
  validation: validation,
148
+ showIcon: true,
149
+ showErrorBorder: true,
147
150
  accessibilityRole: "radiogroup",
148
151
  ...selectProps(rest),
149
152
  children: getStackedContent(radios, {
@@ -182,6 +185,7 @@ RadioGroup.propTypes = { ...selectedSystemPropTypes,
182
185
  label: PropTypes.string,
183
186
  id: PropTypes.string,
184
187
  onChange: PropTypes.func,
188
+ description: PropTypes.string,
185
189
  ref: ABBPropTypes.ref()
186
190
  })),
187
191
 
@@ -120,6 +120,8 @@ const RadioCardGroup = /*#__PURE__*/forwardRef((_ref, ref) => {
120
120
  feedback: feedback,
121
121
  inactive: inactive || readOnly,
122
122
  validation: validation,
123
+ showErrorBorder: true,
124
+ showIcon: true,
123
125
  accessibilityRole: "radiogroup",
124
126
  ...selectProps(rest),
125
127
  children: props => /*#__PURE__*/_jsx(StackContainer, {
@@ -26,6 +26,7 @@ export { default as Notification } from './Notification';
26
26
  export { default as Pagination } from './Pagination';
27
27
  export { default as Progress } from './Progress';
28
28
  export { default as QuickLinks } from './QuickLinks';
29
+ export { default as QuickLinksFeature } from './QuickLinksFeature';
29
30
  export { default as Radio } from './Radio';
30
31
  export * from './Radio';
31
32
  export { default as RadioCard } from './RadioCard';
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "@gorhom/portal": "^1.0.14",
11
11
  "@telus-uds/system-constants": "^1.2.0",
12
- "@telus-uds/system-theme-tokens": "^2.8.0",
12
+ "@telus-uds/system-theme-tokens": "^2.9.0",
13
13
  "airbnb-prop-types": "^2.16.0",
14
14
  "lodash.debounce": "^4.0.8",
15
15
  "lodash.merge": "^4.6.2",
@@ -70,5 +70,5 @@
70
70
  "standard-engine": {
71
71
  "skip": true
72
72
  },
73
- "version": "1.21.0"
73
+ "version": "1.23.0"
74
74
  }
@@ -50,6 +50,8 @@ const ButtonGroup = forwardRef(
50
50
  feedback,
51
51
  name: inputGroupName,
52
52
  copy,
53
+ iconPosition,
54
+
53
55
  accessibilityRole = maxValues === 1
54
56
  ? 'radiogroup' // radiogroup is cross-platform; only web aria has generic groups
55
57
  : Platform.select({ web: 'group', default: 'none' }),
@@ -123,6 +125,8 @@ const ButtonGroup = forwardRef(
123
125
  toggleOneValue(id, event)
124
126
  }
125
127
 
128
+ const iconProp = itemRest.icon || undefined
129
+
126
130
  const itemA11y = {
127
131
  accessibilityState: { checked: isSelected },
128
132
  accessibilityRole: itemA11yRole,
@@ -141,10 +145,12 @@ const ButtonGroup = forwardRef(
141
145
  tokens={getButtonTokens}
142
146
  selected={isSelected}
143
147
  inactive={inactive}
148
+ icon={iconProp}
144
149
  {...selectItemProps({
145
150
  ...itemRest,
146
151
  ...itemA11y
147
152
  })}
153
+ iconPosition={iconPosition}
148
154
  >
149
155
  {label}
150
156
  </ButtonBase>
@@ -213,6 +219,10 @@ ButtonGroup.propTypes = {
213
219
  * Changing the `initialValues` does not change the user's selections.
214
220
  */
215
221
  initialValues: PropTypes.arrayOf(PropTypes.string),
222
+ /**
223
+ * Defines if the icon will be displayed on the right or left side of the label.
224
+ */
225
+ iconPosition: PropTypes.oneOf(['left', 'right']),
216
226
  /**
217
227
  * Main text used to describe this group, used in Fieldset's Legend element.
218
228
  */
@@ -152,6 +152,8 @@ const CheckboxGroup = forwardRef(
152
152
  feedback={feedback}
153
153
  inactive={inactive}
154
154
  validation={validation}
155
+ showIcon
156
+ showErrorBorder
155
157
  {...selectProps(rest)}
156
158
  >
157
159
  {getStackedContent(checkboxes, { space, direction: 'column' })}
@@ -35,10 +35,11 @@ function selectContainerStyles({
35
35
  }
36
36
 
37
37
  // TODO: use stack / spacer when available
38
- function selectIconContainerStyles({ iconGap, iconPosition }) {
38
+ function selectIconContainerStyles({ iconGap, iconPaddingTop, iconPosition }) {
39
39
  const paddingSide = iconPosition === 'right' ? 'paddingLeft' : 'paddingRight'
40
40
  return {
41
- [paddingSide]: iconGap
41
+ [paddingSide]: iconGap,
42
+ paddingTop: iconPaddingTop
42
43
  }
43
44
  }
44
45
 
@@ -56,8 +56,15 @@ const selectIconContainerStyles = ({ iconGap }) => ({
56
56
  * All accessibility props set on this component will be applied to the outer container.
57
57
  */
58
58
  const Feedback = forwardRef(
59
- ({ title, children, id, validation, tokens, variant, ...rest }, ref) => {
60
- const themeTokens = useThemeTokens('Feedback', tokens, { ...variant, validation })
59
+ (
60
+ { title, children, id, validation, tokens, variant, showFeedbackIcon = false, ...rest },
61
+ ref
62
+ ) => {
63
+ const themeTokens = useThemeTokens('Feedback', tokens, {
64
+ ...variant,
65
+ validation,
66
+ icon: showFeedbackIcon
67
+ })
61
68
  const { space } = themeTokens
62
69
 
63
70
  const { icon: IconComponent } = themeTokens
@@ -114,7 +121,8 @@ Feedback.propTypes = {
114
121
  /** @ignore */
115
122
  id: PropTypes.string,
116
123
  tokens: getTokensPropType('Feedback'),
117
- variant: variantProp.propType
124
+ variant: variantProp.propType,
125
+ showFeedbackIcon: PropTypes.bool
118
126
  }
119
127
 
120
128
  export default Feedback
@@ -1,5 +1,6 @@
1
1
  import React, { forwardRef } from 'react'
2
2
  import PropTypes from 'prop-types'
3
+ import { StyleSheet } from 'react-native'
3
4
 
4
5
  import Feedback from '../Feedback'
5
6
  import { spacingProps } from '../utils'
@@ -7,7 +8,6 @@ import FieldsetContainer from './FieldsetContainer'
7
8
  import { getStackedContent } from '../StackView'
8
9
  import InputLabel from '../InputLabel'
9
10
  import useInputSupports from '../InputSupports/useInputSupports'
10
- import Legend from './Legend'
11
11
 
12
12
  /**
13
13
  * An alternative to InputSupports for groups of input elements that, on web, are to be
@@ -23,6 +23,8 @@ const Fieldset = forwardRef(
23
23
  feedback,
24
24
  feedbackPosition = 'top',
25
25
  validation,
26
+ showIcon = false,
27
+ showErrorBorder = false,
26
28
  legend,
27
29
  hint,
28
30
  hintPosition,
@@ -43,19 +45,22 @@ const Fieldset = forwardRef(
43
45
  })
44
46
 
45
47
  const legendContent = legend && (
46
- <Legend>
47
- <InputLabel
48
- copy={copy}
49
- label={legend}
50
- hint={hint}
51
- hintPosition={hintPosition}
52
- hintId={hintId}
53
- tooltip={tooltip}
54
- />
55
- </Legend>
48
+ <InputLabel
49
+ copy={copy}
50
+ label={legend}
51
+ hint={hint}
52
+ hintPosition={hintPosition}
53
+ hintId={hintId}
54
+ tooltip={tooltip}
55
+ />
56
56
  )
57
57
  const feedbackContent = feedback && (
58
- <Feedback id={feedbackId} title={feedback} validation={validation} />
58
+ <Feedback
59
+ id={feedbackId}
60
+ title={feedback}
61
+ validation={validation}
62
+ showFeedbackIcon={showIcon}
63
+ />
59
64
  )
60
65
 
61
66
  // Some accessibility patterns depend on elements being direct children, e.g. fieldset -> legend,
@@ -68,6 +73,9 @@ const Fieldset = forwardRef(
68
73
  ? [legendContent, feedbackContent, childContent]
69
74
  : [legendContent, childContent, feedbackContent]
70
75
  const stackedContent = getStackedContent(orderedContent, { space, preserveFragments: true })
76
+ const borderStyle =
77
+ (validation === 'error' && showErrorBorder && staticStyles.errorBorder) ||
78
+ staticStyles.noBorder
71
79
 
72
80
  return (
73
81
  <FieldsetContainer
@@ -75,12 +83,28 @@ const Fieldset = forwardRef(
75
83
  inactive={inactive}
76
84
  accessibilityRole={accessibilityRole}
77
85
  name={fieldsetName}
86
+ borderStyle={borderStyle}
87
+ showBorderStyle={showErrorBorder}
78
88
  >
79
89
  {stackedContent}
80
90
  </FieldsetContainer>
81
91
  )
82
92
  }
83
93
  )
94
+ const staticStyles = StyleSheet.create({
95
+ errorBorder: {
96
+ border: true,
97
+ borderWidth: 1,
98
+ borderColor: 'red',
99
+ borderRadius: 10,
100
+ padding: 8
101
+ },
102
+ noBorder: {
103
+ padding: 9,
104
+ border: 'unset'
105
+ }
106
+ })
107
+
84
108
  Fieldset.displayName = 'Fieldset'
85
109
 
86
110
  Fieldset.propTypes = {
@@ -136,7 +160,15 @@ Fieldset.propTypes = {
136
160
  /**
137
161
  * Use to visually mark an input as valid or invalid.
138
162
  */
139
- validation: PropTypes.oneOf(['error', 'success'])
163
+ validation: PropTypes.oneOf(['error', 'success']),
164
+ /**
165
+ * Use to show error or success icon in the feedback
166
+ */
167
+ showIcon: PropTypes.bool,
168
+ /**
169
+ * Use to show border in case of error for a group of components
170
+ */
171
+ showErrorBorder: PropTypes.bool
140
172
  }
141
173
 
142
174
  export default Fieldset
@@ -7,17 +7,32 @@ import cssReset from './cssReset'
7
7
  * On Web, wraps children with a HTML `<fieldset>` and sets its attributes as necessary.
8
8
  */
9
9
  const FieldsetContainer = forwardRef(
10
- ({ children, inactive, accessibilityRole, name: fieldsetName }, ref) => (
11
- <fieldset
12
- ref={ref}
13
- disabled={inactive}
14
- style={cssReset}
15
- role={accessibilityRole}
16
- name={fieldsetName}
17
- >
18
- {children}
19
- </fieldset>
20
- )
10
+ (
11
+ {
12
+ children,
13
+ inactive,
14
+ accessibilityRole,
15
+ name: fieldsetName,
16
+ showBorderStyle = false,
17
+ borderStyle
18
+ },
19
+ ref
20
+ ) => {
21
+ // If needs border for error design or reset the component style
22
+ const styleContainer = showBorderStyle ? borderStyle : cssReset
23
+
24
+ return (
25
+ <fieldset
26
+ ref={ref}
27
+ disabled={inactive}
28
+ style={styleContainer}
29
+ role={accessibilityRole}
30
+ name={fieldsetName}
31
+ >
32
+ {children}
33
+ </fieldset>
34
+ )
35
+ }
21
36
  )
22
37
  FieldsetContainer.displayName = 'FieldsetContainer'
23
38
 
@@ -25,7 +40,9 @@ FieldsetContainer.propTypes = {
25
40
  accessibilityRole: PropTypes.string,
26
41
  children: PropTypes.node,
27
42
  inactive: PropTypes.bool,
28
- name: PropTypes.string
43
+ name: PropTypes.string,
44
+ showBorderStyle: PropTypes.bool,
45
+ borderStyle: PropTypes.object
29
46
  }
30
47
 
31
48
  export default FieldsetContainer
@@ -91,6 +91,7 @@ PressableListItemBase.propTypes = {
91
91
  ...withLinkRouter.propTypes,
92
92
  href: PropTypes.string,
93
93
  onPress: PropTypes.func,
94
+ // eslint-disable-next-line react/forbid-prop-types
94
95
  tokens: PropTypes.any,
95
96
  icon: PropTypes.elementType,
96
97
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
@@ -0,0 +1,65 @@
1
+ import React, { forwardRef, Children, cloneElement } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import { StackWrap } from '../StackView'
4
+
5
+ import { useThemeTokens } from '../ThemeProvider'
6
+ import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils'
7
+
8
+ // pass through and type relevant system props - add more sets for interactive components
9
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
10
+
11
+ const isQuickListItem = (element) => {
12
+ const elementName = element?.type?.displayName || element?.type?.name
13
+ return Boolean(elementName.match(/QuickLinksFeatureItem/))
14
+ }
15
+
16
+ /**
17
+ * QuickLinksFeature renders a list of interactive items.
18
+ * - This is the base component that is used as a wrapper and accepts a List of `QuickLinksFeature.Item`
19
+ */
20
+ const QuickLinksFeature = forwardRef(({ tokens, variant, tag = 'ul', children, ...rest }, ref) => {
21
+ const { stackGap, stackJustify, stackSpace } = useThemeTokens(
22
+ 'QuickLinksFeature',
23
+ tokens,
24
+ variant
25
+ )
26
+
27
+ const items = Children.map(children, (child) => {
28
+ if (isQuickListItem(child)) {
29
+ return cloneElement(child, child.props)
30
+ }
31
+
32
+ return null
33
+ })
34
+
35
+ return (
36
+ <StackWrap
37
+ space={stackSpace}
38
+ gap={stackGap}
39
+ tokens={{ justifyContent: stackJustify }}
40
+ tag={tag}
41
+ ref={ref}
42
+ {...selectProps(rest)}
43
+ >
44
+ {items}
45
+ </StackWrap>
46
+ )
47
+ })
48
+
49
+ QuickLinksFeature.displayName = 'QuickLinksFeature'
50
+
51
+ QuickLinksFeature.propTypes = {
52
+ ...selectedSystemPropTypes,
53
+ tokens: getTokensPropType('QuickLinksFeature'),
54
+ variant: variantProp.propType,
55
+ /**
56
+ * Default wrapper tag, by default it's "ul"
57
+ */
58
+ tag: PropTypes.string,
59
+ /**
60
+ * QuickLinksFeature.Item component
61
+ */
62
+ children: PropTypes.node
63
+ }
64
+
65
+ export default QuickLinksFeature