@utilitywarehouse/hearth-react-native 0.21.0 → 0.22.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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @utilitywarehouse/hearth-react-native@0.21.0 build /home/runner/work/hearth/hearth/packages/react-native
2
+ > @utilitywarehouse/hearth-react-native@0.22.0 build /home/runner/work/hearth/hearth/packages/react-native
3
3
  > tsc
4
4
 
@@ -1,5 +1,5 @@
1
1
 
2
- > @utilitywarehouse/hearth-react-native@0.21.0 lint /home/runner/work/hearth/hearth/packages/react-native
2
+ > @utilitywarehouse/hearth-react-native@0.22.0 lint /home/runner/work/hearth/hearth/packages/react-native
3
3
  > TIMING=1 eslint .
4
4
 
5
5
 
@@ -58,15 +58,15 @@
58
58
 
59
59
  ✖ 25 problems (0 errors, 25 warnings)
60
60
 
61
- Rule | Time (ms) | Relative
62
- :---------------------------------|----------:|--------:
63
- @typescript-eslint/no-unused-vars | 1327.577 | 60.2%
64
- react-hooks/exhaustive-deps | 77.842 | 3.5%
65
- no-global-assign | 77.325 | 3.5%
66
- react-hooks/rules-of-hooks | 64.813 | 2.9%
67
- no-misleading-character-class | 44.059 | 2.0%
68
- no-loss-of-precision | 40.431 | 1.8%
69
- no-unexpected-multiline | 40.191 | 1.8%
70
- @typescript-eslint/ban-ts-comment | 32.434 | 1.5%
71
- no-useless-escape | 27.764 | 1.3%
72
- no-fallthrough | 27.614 | 1.3%
61
+ Rule | Time (ms) | Relative
62
+ :-------------------------------------------------|----------:|--------:
63
+ @typescript-eslint/no-unused-vars | 1687.263 | 65.5%
64
+ react-hooks/rules-of-hooks | 78.867 | 3.1%
65
+ react-hooks/exhaustive-deps | 78.504 | 3.0%
66
+ no-global-assign | 75.145 | 2.9%
67
+ no-unexpected-multiline | 55.153 | 2.1%
68
+ no-loss-of-precision | 46.457 | 1.8%
69
+ @typescript-eslint/ban-ts-comment | 45.439 | 1.8%
70
+ no-misleading-character-class | 37.162 | 1.4%
71
+ @typescript-eslint/triple-slash-reference | 28.294 | 1.1%
72
+ @typescript-eslint/no-unnecessary-type-constraint | 20.347 | 0.8%
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @utilitywarehouse/hearth-react-native
2
2
 
3
+ ## 0.22.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#968](https://github.com/utilitywarehouse/hearth/pull/968) [`cee5811`](https://github.com/utilitywarehouse/hearth/commit/cee5811020af02fe754d8311ec8313c1793f108a) Thanks [@jordmccord](https://github.com/jordmccord)! - 🌟 [FEATURE]: Add `badge` support to Radio and Checkbox (including tiles).
8
+
9
+ **Components affected**:
10
+ - `Radio`
11
+ - `RadioTile`
12
+ - `Checkbox`
13
+ - `CheckboxTile`
14
+
15
+ **Developer changes**:
16
+ You can now pass a `badge` React node to render beneath helper text. No changes required unless you want to use the new prop.
17
+
18
+ ### Patch Changes
19
+
20
+ - [#966](https://github.com/utilitywarehouse/hearth/pull/966) [`4e9f3f0`](https://github.com/utilitywarehouse/hearth/commit/4e9f3f0284e50da5ba4e49e132dac745a1a8a68d) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Allow Card layout props and remove forced alignment
21
+
22
+ Card now accepts flex layout and display props, and it no longer forces `alignItems: flex-start` on the root, so custom alignment works as expected.
23
+
24
+ - [#969](https://github.com/utilitywarehouse/hearth/pull/969) [`c5c988b`](https://github.com/utilitywarehouse/hearth/commit/c5c988b65f1133b85b822037b086a524bc1255e3) Thanks [@jordmccord](https://github.com/jordmccord)! - 🐛 [FIX]: Render the Modal footer in navigation modals
25
+
3
26
  ## 0.21.0
4
27
 
5
28
  ### Minor Changes
@@ -1,17 +1,13 @@
1
- import { PressableProps, ViewStyle } from 'react-native';
2
- import { GapProps, MarginProps, SpacingValues } from '../../types';
3
- interface CardProps extends PressableProps, MarginProps, GapProps {
1
+ import { PressableProps } from 'react-native';
2
+ import { DisplayProps, FlexLayoutProps, GapProps, MarginProps, SpacingValues } from '../../types';
3
+ interface CardProps extends PressableProps, MarginProps, GapProps, FlexLayoutProps, Omit<DisplayProps, 'direction'> {
4
4
  variant?: 'emphasis' | 'subtle';
5
5
  colorScheme?: 'neutralStrong' | 'neutralSubtle' | 'brand' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'pig';
6
6
  shadowColor?: 'functional' | 'brand' | 'energy' | 'broadband' | 'mobile' | 'insurance' | 'cashback' | 'pig';
7
7
  noPadding?: boolean;
8
8
  disabled?: boolean;
9
9
  spacing?: SpacingValues;
10
- /** @deprecated Use `spacing` instead. The `gap` prop will be removed in a future release. */
10
+ /** @deprecated Use `spacing` instead. The `space` prop will be removed in a future release. */
11
11
  space?: SpacingValues;
12
- alignItems?: ViewStyle['alignItems'];
13
- justifyContent?: ViewStyle['justifyContent'];
14
- flexDirection?: ViewStyle['flexDirection'];
15
- flexWrap?: ViewStyle['flexWrap'];
16
12
  }
17
13
  export default CardProps;
@@ -70,7 +70,6 @@ Card.displayName = 'Card';
70
70
  const styles = StyleSheet.create(theme => ({
71
71
  card: {
72
72
  overflow: 'hidden',
73
- alignItems: 'flex-start',
74
73
  borderRadius: theme.components.card.borderRadius,
75
74
  variants: {
76
75
  spacing: theme.globalStyle.variants.spacing,
@@ -10,7 +10,7 @@ declare const CheckboxIcon: import("react").ForwardRefExoticComponent<import("re
10
10
  }>;
11
11
  declare const CheckboxLabel: import("react").ForwardRefExoticComponent<import("react").RefAttributes<import("../Label/Label.props").default> & Omit<import("../Label/Label.props").default, "ref">>;
12
12
  declare const Checkbox: {
13
- ({ children, label, disabled, checked, helperIcon, helperText, invalidText, validText, validationStatus: validation, showValidationIcon, type, image, value, ...props }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
13
+ ({ children, label, disabled, checked, helperIcon, helperText, badge, invalidText, validText, validationStatus: validation, showValidationIcon, type, image, value, ...props }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
14
14
  displayName: string;
15
15
  };
16
16
  declare const CheckboxTile: {
@@ -25,12 +25,12 @@ CheckboxGroup.displayName = 'CheckboxGroup';
25
25
  CheckboxIndicator.displayName = 'CheckboxIndicator';
26
26
  CheckboxIcon.displayName = 'CheckboxIcon';
27
27
  CheckboxLabel.displayName = 'CheckboxLabel';
28
- const Checkbox = ({ children, label, disabled, checked, helperIcon, helperText, invalidText, validText, validationStatus: validation, showValidationIcon, type = 'default', image, value, ...props }) => {
28
+ const Checkbox = ({ children, label, disabled, checked, helperIcon, helperText, badge, invalidText, validText, validationStatus: validation, showValidationIcon, type = 'default', image, value, ...props }) => {
29
29
  const { validationStatus: fieldValidationStatus } = useFormFieldContext();
30
30
  const { validationStatus: groupValidationStatus, type: groupType } = useCheckboxGroupContext();
31
31
  const validationStatus = fieldValidationStatus ?? groupValidationStatus ?? validation ?? 'initial';
32
32
  const checkboxType = groupType ?? type;
33
- const checkboxChildren = children ? (children) : (_jsxs(_Fragment, { children: [_jsx(CheckboxIndicator, { children: _jsx(CheckboxIcon, {}) }), image ? image : null, _jsxs(CheckboxTextContent, { children: [!!label && _jsx(CheckboxLabel, { children: label }), !!helperText && _jsx(Helper, { disabled: disabled, icon: helperIcon, text: helperText }), validationStatus === 'invalid' && !!invalidText && (_jsx(Helper, { showIcon: showValidationIcon, disabled: disabled, validationStatus: "invalid", text: invalidText })), validationStatus === 'valid' && !!validText && (_jsx(Helper, { disabled: disabled, showIcon: showValidationIcon, validationStatus: "valid", text: validText }))] })] }));
33
+ const checkboxChildren = children ? (children) : (_jsxs(_Fragment, { children: [_jsx(CheckboxIndicator, { children: _jsx(CheckboxIcon, {}) }), image ? image : null, _jsxs(CheckboxTextContent, { children: [!!label && _jsx(CheckboxLabel, { children: label }), !!helperText && _jsx(Helper, { disabled: disabled, icon: helperIcon, text: helperText }), badge ? badge : null, validationStatus === 'invalid' && !!invalidText && (_jsx(Helper, { showIcon: showValidationIcon, disabled: disabled, validationStatus: "invalid", text: invalidText })), validationStatus === 'valid' && !!validText && (_jsx(Helper, { disabled: disabled, showIcon: showValidationIcon, validationStatus: "valid", text: validText }))] })] }));
34
34
  return (_jsx(CheckboxComponent, { ...props, value: (value ?? '').toString(), isDisabled: disabled, isChecked: checked, children: checkboxType === 'tile' ? (_jsx(CheckboxTileRoot, { children: checkboxChildren })) : (checkboxChildren) }));
35
35
  };
36
36
  const CheckboxTile = ({ type = 'tile', ...props }) => {
@@ -17,6 +17,7 @@ type CheckboxWithChildrenProps = {
17
17
  label?: never;
18
18
  helperText?: never;
19
19
  helperIcon?: never;
20
+ badge?: never;
20
21
  invalidText?: never;
21
22
  validText?: never;
22
23
  showValidationIcon?: never;
@@ -27,6 +28,7 @@ type CheckboxWithoutChildrenProps = {
27
28
  label?: string;
28
29
  helperText?: string;
29
30
  helperIcon?: ComponentType;
31
+ badge?: ReactNode;
30
32
  invalidText?: string;
31
33
  validText?: string;
32
34
  showValidationIcon?: boolean;
@@ -107,7 +107,7 @@ const Modal = ({ ref, children, heading, description, showCloseButton = true, pr
107
107
  showHandle: props.showHandle,
108
108
  });
109
109
  const footer = (_jsxs(View, { style: styles.footer, children: [onPressPrimaryButton && primaryButtonText ? (_jsx(Button, { onPress: handlePrimaryButtonPress, text: primaryButtonText, ...primaryButtonProps, variant: primaryButtonProps?.variant ?? 'solid', colorScheme: primaryButtonProps?.colorScheme ?? 'highlight' })) : null, onPressSecondaryButton && secondaryButtonText ? (_jsx(Button, { onPress: handleSecondaryButtonPress, text: secondaryButtonText, ...secondaryButtonProps, variant: secondaryButtonProps?.variant ?? 'outline', colorScheme: secondaryButtonProps?.colorScheme ?? 'functional' })) : null] }));
110
- const content = (_jsx(_Fragment, { children: loading ? (_jsxs(View, { style: styles.loadingContainer, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Loading' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsx(Spinner, { size: "lg" }), _jsx(Heading, { size: "lg", textAlign: "center", children: loadingHeading })] })) : (_jsxs(View, { style: styles.container, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Modal content' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsxs(View, { style: styles.header, children: [_jsxs(View, { style: styles.headerTextContent, children: [heading && !image ? (_jsx(Heading, { size: "lg", accessible: true, children: heading })) : null, description && !image ? _jsx(BodyText, { accessible: true, children: description }) : null] }), showCloseButton ? (_jsx(UnstyledIconButton, { icon: CloseMediumIcon, onPress: handleCloseButtonPress, accessibilityLabel: "Close modal", ...closeButtonProps })) : null] }), image ? (_jsxs(View, { style: styles.imageContainer, children: [image, _jsxs(View, { style: styles.textContent, children: [heading ? (_jsx(Heading, { size: "lg", textAlign: "center", accessible: true, children: heading })) : null, description ? (_jsx(BodyText, { textAlign: "center", accessible: true, children: description })) : null] })] })) : null, children, !stickyFooter && !noButtons ? footer : null] })) }));
110
+ const content = (_jsx(_Fragment, { children: loading ? (_jsxs(View, { style: styles.loadingContainer, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Loading' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsx(Spinner, { size: "lg" }), _jsx(Heading, { size: "lg", textAlign: "center", children: loadingHeading })] })) : (_jsxs(View, { style: styles.container, accessible: Platform.OS === 'android' ? true : undefined, accessibilityLabel: Platform.OS === 'android' ? 'Modal content' : undefined, screenReaderFocusable: true, ref: viewRef, children: [_jsxs(View, { style: styles.header, children: [_jsxs(View, { style: styles.headerTextContent, children: [heading && !image ? (_jsx(Heading, { size: "lg", accessible: true, children: heading })) : null, description && !image ? _jsx(BodyText, { accessible: true, children: description }) : null] }), showCloseButton ? (_jsx(UnstyledIconButton, { icon: CloseMediumIcon, onPress: handleCloseButtonPress, accessibilityLabel: "Close modal", ...closeButtonProps })) : null] }), image ? (_jsxs(View, { style: styles.imageContainer, children: [image, _jsxs(View, { style: styles.textContent, children: [heading ? (_jsx(Heading, { size: "lg", textAlign: "center", accessible: true, children: heading })) : null, description ? (_jsx(BodyText, { textAlign: "center", accessible: true, children: description })) : null] })] })) : null, children, (!stickyFooter || inNavModal) && !noButtons ? footer : null] })) }));
111
111
  const renderFooter = useCallback((props) => (_jsx(BottomSheetFooter, { ...props, children: _jsx(View, { style: styles.footerWrap, children: footer }) })), [
112
112
  onPressPrimaryButton,
113
113
  primaryButtonText,
@@ -10,7 +10,7 @@ declare const RadioIcon: import("react").ForwardRefExoticComponent<import("react
10
10
  }>;
11
11
  declare const RadioLabel: import("react").ForwardRefExoticComponent<import("react").RefAttributes<import("../Label/Label.props").default> & Omit<import("../Label/Label.props").default, "ref">>;
12
12
  declare const Radio: {
13
- ({ children, label, disabled, helperIcon, helperText, invalidText, validText, validationStatus: validation, showValidationIcon, type, image, ...props }: RadioProps): import("react/jsx-runtime").JSX.Element;
13
+ ({ children, label, disabled, helperIcon, helperText, badge, invalidText, validText, validationStatus: validation, showValidationIcon, type, image, ...props }: RadioProps): import("react/jsx-runtime").JSX.Element;
14
14
  displayName: string;
15
15
  };
16
16
  declare const RadioTile: {
@@ -25,12 +25,12 @@ RadioGroup.displayName = 'RadioGroup';
25
25
  RadioIndicator.displayName = 'RadioIndicator';
26
26
  RadioIcon.displayName = 'RadioIcon';
27
27
  RadioLabel.displayName = 'RadioLabel';
28
- const Radio = ({ children, label, disabled, helperIcon, helperText, invalidText, validText, validationStatus: validation, showValidationIcon, type = 'default', image, ...props }) => {
28
+ const Radio = ({ children, label, disabled, helperIcon, helperText, badge, invalidText, validText, validationStatus: validation, showValidationIcon, type = 'default', image, ...props }) => {
29
29
  const { validationStatus: fieldValidationStatus } = useFormFieldContext();
30
30
  const { validationStatus: groupValidationStatus, type: groupType } = useRadioGroupContext();
31
31
  const validationStatus = fieldValidationStatus ?? groupValidationStatus ?? validation ?? 'initial';
32
32
  const radioType = groupType ?? type;
33
- const radioChildren = children ? (children) : (_jsxs(_Fragment, { children: [_jsx(RadioIndicator, { children: _jsx(RadioIcon, {}) }), image ? image : null, _jsxs(RadioTextContent, { children: [!!label && _jsx(RadioLabel, { children: label }), !!helperText && _jsx(Helper, { disabled: disabled, icon: helperIcon, text: helperText }), validationStatus === 'invalid' && !!invalidText && (_jsx(Helper, { showIcon: showValidationIcon, disabled: disabled, validationStatus: "invalid", text: invalidText })), validationStatus === 'valid' && !!validText && (_jsx(Helper, { disabled: disabled, showIcon: showValidationIcon, validationStatus: "valid", text: validText }))] })] }));
33
+ const radioChildren = children ? (children) : (_jsxs(_Fragment, { children: [_jsx(RadioIndicator, { children: _jsx(RadioIcon, {}) }), image ? image : null, _jsxs(RadioTextContent, { children: [!!label && _jsx(RadioLabel, { children: label }), !!helperText && _jsx(Helper, { disabled: disabled, icon: helperIcon, text: helperText }), badge ? badge : null, validationStatus === 'invalid' && !!invalidText && (_jsx(Helper, { showIcon: showValidationIcon, disabled: disabled, validationStatus: "invalid", text: invalidText })), validationStatus === 'valid' && !!validText && (_jsx(Helper, { disabled: disabled, showIcon: showValidationIcon, validationStatus: "valid", text: validText }))] })] }));
34
34
  return (_jsx(RadioComponent, { ...props, isDisabled: disabled, children: radioType === 'tile' ? _jsx(RadioTileRoot, { children: radioChildren }) : radioChildren }));
35
35
  };
36
36
  const RadioTile = ({ type = 'tile', ...props }) => _jsx(Radio, { ...props, type: type });
@@ -12,6 +12,7 @@ interface RadioWithChildrenProps extends RadioBaseProps {
12
12
  label?: never;
13
13
  helperText?: never;
14
14
  helperIcon?: never;
15
+ badge?: never;
15
16
  invalidText?: never;
16
17
  validText?: never;
17
18
  showValidationIcon?: never;
@@ -22,6 +23,7 @@ interface RadioWithoutChildrenProps extends RadioBaseProps {
22
23
  label?: string;
23
24
  helperText?: string;
24
25
  helperIcon?: ComponentType;
26
+ badge?: ReactNode;
25
27
  invalidText?: string;
26
28
  validText?: string;
27
29
  showValidationIcon?: boolean;
@@ -32,7 +32,7 @@ const NextPrevPage: React.FC<NextPrevPageProps> = ({
32
32
  <div className="sb-unstyled">
33
33
  <View style={styles.container}>
34
34
  {!!prevLink && (
35
- <Card gap="100">
35
+ <Card gap="100" alignItems="flex-start">
36
36
  {!!prevTitle && <Heading size="sm">{prevTitle}</Heading>}
37
37
  <CardPressHandler>
38
38
  <Link
@@ -47,7 +47,7 @@ const NextPrevPage: React.FC<NextPrevPageProps> = ({
47
47
  )}
48
48
  <div />
49
49
  {!!nextLink && (
50
- <Card gap="100">
50
+ <Card gap="100" alignItems="flex-start">
51
51
  {!!nextTitle && <Heading size="sm">{nextTitle}</Heading>}
52
52
  <CardPressHandler>
53
53
  <Link onPress={() => openLink(nextLink)}>Next Page</Link>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@utilitywarehouse/hearth-react-native",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Utility Warehouse React Native UI library",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -42,13 +42,13 @@
42
42
  "react": "^19.1.0",
43
43
  "react-native": "0.80.0",
44
44
  "react-native-edge-to-edge": "1.6.1",
45
- "react-native-gesture-handler": "2.26.0",
45
+ "react-native-gesture-handler": "2.28.0",
46
46
  "react-native-nitro-modules": "^0.31.4",
47
47
  "react-native-reanimated": "4.1.3",
48
48
  "react-native-svg": "^15.12.1",
49
49
  "react-native-unistyles": "3.0.17",
50
50
  "react-native-web": "^0.20.0",
51
- "react-native-worklets": "^0.6.1",
51
+ "react-native-worklets": "^0.5.1",
52
52
  "remark-gfm": "^4.0.1",
53
53
  "storybook": "^10.2.1",
54
54
  "typescript": "^5.7.3",
@@ -66,7 +66,7 @@
66
66
  "@utilitywarehouse/hearth-react-native-icons": "0.8.0",
67
67
  "react": ">=17 || ^18.0.0 || ^19.0.0",
68
68
  "react-native": ">=0.77",
69
- "react-native-gesture-handler": "^2.22.0",
69
+ "react-native-gesture-handler": ">=2.0.0",
70
70
  "react-native-reanimated": "3.x || ^4.x",
71
71
  "react-native-svg": ">=13.4.0",
72
72
  "react-native-unistyles": ">=3.0.0",
@@ -1,7 +1,8 @@
1
- import { PressableProps, ViewStyle } from 'react-native';
2
- import { GapProps, MarginProps, SpacingValues } from '../../types';
1
+ import { PressableProps } from 'react-native';
2
+ import { DisplayProps, FlexLayoutProps, GapProps, MarginProps, SpacingValues } from '../../types';
3
3
 
4
- interface CardProps extends PressableProps, MarginProps, GapProps {
4
+ interface CardProps
5
+ extends PressableProps, MarginProps, GapProps, FlexLayoutProps, Omit<DisplayProps, 'direction'> {
5
6
  variant?: 'emphasis' | 'subtle';
6
7
  colorScheme?:
7
8
  | 'neutralStrong'
@@ -25,12 +26,8 @@ interface CardProps extends PressableProps, MarginProps, GapProps {
25
26
  noPadding?: boolean;
26
27
  disabled?: boolean;
27
28
  spacing?: SpacingValues;
28
- /** @deprecated Use `spacing` instead. The `gap` prop will be removed in a future release. */
29
+ /** @deprecated Use `spacing` instead. The `space` prop will be removed in a future release. */
29
30
  space?: SpacingValues;
30
- alignItems?: ViewStyle['alignItems'];
31
- justifyContent?: ViewStyle['justifyContent'];
32
- flexDirection?: ViewStyle['flexDirection'];
33
- flexWrap?: ViewStyle['flexWrap'];
34
31
  }
35
32
 
36
33
  export default CardProps;
@@ -123,7 +123,6 @@ Card.displayName = 'Card';
123
123
  const styles = StyleSheet.create(theme => ({
124
124
  card: {
125
125
  overflow: 'hidden',
126
- alignItems: 'flex-start',
127
126
  borderRadius: theme.components.card.borderRadius,
128
127
  variants: {
129
128
  spacing: theme.globalStyle.variants.spacing,
@@ -87,6 +87,7 @@ const MyComponent = () => {
87
87
  | `label` | `string` | - | The label to be displayed next to the checkbox. |
88
88
  | `helperText` | `string` | - | The helper text to be displayed below the checkbox. |
89
89
  | `helperIcon` | `React.ComponentType` | - | The icon to be displayed next to the helper text. |
90
+ | `badge` | `ReactNode` | - | The badge to be displayed below the helper text. |
90
91
  | `invalidText` | `string` | - | The invalid text to be displayed below the checkbox. |
91
92
  | `validText` | `string` | - | The valid text to be displayed below the checkbox. |
92
93
  | `showValidationIcon` | `boolean` | `true` | Whether to show the validation icon. |
@@ -23,6 +23,7 @@ type CheckboxWithChildrenProps = {
23
23
  label?: never;
24
24
  helperText?: never;
25
25
  helperIcon?: never;
26
+ badge?: never;
26
27
  invalidText?: never;
27
28
  validText?: never;
28
29
  showValidationIcon?: never;
@@ -34,6 +35,7 @@ type CheckboxWithoutChildrenProps = {
34
35
  label?: string;
35
36
  helperText?: string;
36
37
  helperIcon?: ComponentType;
38
+ badge?: ReactNode;
37
39
  invalidText?: string;
38
40
  validText?: string;
39
41
  showValidationIcon?: boolean;
@@ -5,6 +5,7 @@ import { Checkbox, CheckboxGroup, CheckboxImage } from '.';
5
5
  import bankLogo from '../../../docs/assets/bank-logo.png';
6
6
  import bankLogo1 from '../../../docs/assets/bank-logo1.png';
7
7
  import { VariantTitle } from '../../../docs/components';
8
+ import { Badge } from '../Badge';
8
9
 
9
10
  const meta = {
10
11
  title: 'Stories / Checkbox',
@@ -133,6 +134,31 @@ export const WithImage: Story = {
133
134
  ),
134
135
  };
135
136
 
137
+ export const WithBadge: Story = {
138
+ args: {
139
+ label: 'Label',
140
+ helperText: 'Helper text',
141
+ },
142
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
143
+ render: ({ checked: checkedArg = false, onChange, ...args }) => {
144
+ const [checked, setChecked] = React.useState(checkedArg);
145
+ useEffect(() => {
146
+ setChecked(checkedArg);
147
+ }, [checkedArg]);
148
+ return (
149
+ <Checkbox
150
+ onChange={val => {
151
+ console.log('-----');
152
+ setChecked(val);
153
+ }}
154
+ badge={<Badge>New</Badge>}
155
+ {...args}
156
+ checked={checked}
157
+ />
158
+ );
159
+ },
160
+ };
161
+
136
162
  export const Variants: Story = {
137
163
  render: () => {
138
164
  const [values, setValues] = React.useState(['Label 1']);
@@ -36,6 +36,7 @@ const Checkbox = ({
36
36
  checked,
37
37
  helperIcon,
38
38
  helperText,
39
+ badge,
39
40
  invalidText,
40
41
  validText,
41
42
  validationStatus: validation,
@@ -61,6 +62,7 @@ const Checkbox = ({
61
62
  <CheckboxTextContent>
62
63
  {!!label && <CheckboxLabel>{label}</CheckboxLabel>}
63
64
  {!!helperText && <Helper disabled={disabled} icon={helperIcon} text={helperText} />}
65
+ {badge ? badge : null}
64
66
  {validationStatus === 'invalid' && !!invalidText && (
65
67
  <Helper
66
68
  showIcon={showValidationIcon}
@@ -254,7 +254,7 @@ const Modal = ({
254
254
  </View>
255
255
  ) : null}
256
256
  {children}
257
- {!stickyFooter && !noButtons ? footer : null}
257
+ {(!stickyFooter || inNavModal) && !noButtons ? footer : null}
258
258
  </View>
259
259
  )}
260
260
  </>
@@ -100,6 +100,7 @@ const MyComponent = () => {
100
100
  | `label` | `string` | - | The label to be displayed next to the radio. |
101
101
  | `helperText` | `string` | - | The helper text to be displayed below the radio. |
102
102
  | `helperIcon` | `React.ComponentType` | - | The icon to be displayed next to the helper text. |
103
+ | `badge` | `ReactNode` | - | The badge to be displayed below the helper text. |
103
104
  | `invalidText` | `string` | - | The invalid text to be displayed below the radio. |
104
105
  | `validText` | `string` | - | The valid text to be displayed below the radio. |
105
106
  | `showValidationIcon` | `boolean` | `true` | Whether to show the validation icon. |
@@ -14,6 +14,7 @@ interface RadioWithChildrenProps extends RadioBaseProps {
14
14
  label?: never;
15
15
  helperText?: never;
16
16
  helperIcon?: never;
17
+ badge?: never;
17
18
  invalidText?: never;
18
19
  validText?: never;
19
20
  showValidationIcon?: never;
@@ -25,6 +26,7 @@ interface RadioWithoutChildrenProps extends RadioBaseProps {
25
26
  label?: string;
26
27
  helperText?: string;
27
28
  helperIcon?: ComponentType;
29
+ badge?: ReactNode;
28
30
  invalidText?: string;
29
31
  validText?: string;
30
32
  showValidationIcon?: boolean;
@@ -5,6 +5,7 @@ import { Radio, RadioGroup, RadioImage } from '.';
5
5
  import bankLogo from '../../../docs/assets/bank-logo.png';
6
6
  import bankLogo1 from '../../../docs/assets/bank-logo1.png';
7
7
  import { VariantTitle } from '../../../docs/components';
8
+ import { Badge } from '../Badge';
8
9
  import { Flex } from '../Flex';
9
10
  import { FormField } from '../FormField';
10
11
 
@@ -136,6 +137,27 @@ export const WithImage: Story = {
136
137
  ),
137
138
  };
138
139
 
140
+ export const WithBadge: Story = {
141
+ args: {
142
+ value: 'Option 1',
143
+ label: 'Label',
144
+ helperText: 'Helper text',
145
+ },
146
+ render: args => (
147
+ <RadioGroup>
148
+ <Radio
149
+ aria-label="Label 1"
150
+ onChange={(checked: boolean) => {
151
+ console.log(checked, '###');
152
+ }}
153
+ nativeID="Radio-1"
154
+ badge={<Badge>New</Badge>}
155
+ {...args}
156
+ />
157
+ </RadioGroup>
158
+ ),
159
+ };
160
+
139
161
  export const Variants: Story = {
140
162
  parameters: {
141
163
  controls: { exclude: ['value', 'label', 'disabled'] },
@@ -36,6 +36,7 @@ const Radio = ({
36
36
  disabled,
37
37
  helperIcon,
38
38
  helperText,
39
+ badge,
39
40
  invalidText,
40
41
  validText,
41
42
  validationStatus: validation,
@@ -60,6 +61,7 @@ const Radio = ({
60
61
  <RadioTextContent>
61
62
  {!!label && <RadioLabel>{label}</RadioLabel>}
62
63
  {!!helperText && <Helper disabled={disabled} icon={helperIcon} text={helperText} />}
64
+ {badge ? badge : null}
63
65
  {validationStatus === 'invalid' && !!invalidText && (
64
66
  <Helper
65
67
  showIcon={showValidationIcon}
@@ -9,6 +9,9 @@ figma.connect(
9
9
  helperText: figma.boolean('Helper text?', {
10
10
  true: figma.string('Helper text'),
11
11
  }),
12
+ badge: figma.boolean('Badge?', {
13
+ true: figma.children('Badge'),
14
+ }),
12
15
  label: figma.string('Label'),
13
16
  image: figma.boolean('Image?', {
14
17
  true: figma.instance('Radio Image'),
@@ -24,6 +27,7 @@ figma.connect(
24
27
  <RadioTile
25
28
  label={props.label}
26
29
  helperText={props.helperText}
30
+ badge={props.badge}
27
31
  image={props.image}
28
32
  checked={props.checked}
29
33
  disabled={props.indicator.disabled}