@utilitywarehouse/hearth-react-native 0.15.3 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +67 -6
- package/CHANGELOG.md +73 -6
- package/build/components/Avatar/Avatar.js +0 -2
- package/build/components/Banner/Banner.d.ts +1 -1
- package/build/components/Banner/Banner.js +3 -1
- package/build/components/Carousel/Carousel.js +1 -1
- package/build/components/Checkbox/CheckboxGroup.d.ts +1 -1
- package/build/components/Checkbox/CheckboxGroup.js +2 -2
- package/build/components/Checkbox/CheckboxGroup.props.d.ts +2 -1
- package/build/components/CurrencyInput/CurrencyInput.d.ts +1 -1
- package/build/components/CurrencyInput/CurrencyInput.js +2 -6
- package/build/components/CurrencyInput/CurrencyInput.props.d.ts +6 -0
- package/build/components/DateInput/DateInput.js +1 -0
- package/build/components/DateInput/DateInputSegment.js +2 -3
- package/build/components/DatePicker/DatePicker.js +8 -4
- package/build/components/DatePicker/DatePickerHeader/DatePickerHeader.props.d.ts +0 -1
- package/build/components/DatePicker/DatePickerHeader/index.js +1 -1
- package/build/components/DatePicker/index.d.ts +1 -0
- package/build/components/DatePicker/polyfill.js +3 -3
- package/build/components/DatePicker/time-picker/wheel-web.js +1 -3
- package/build/components/DatePickerInput/DatePickerInput.d.ts +1 -1
- package/build/components/DatePickerInput/DatePickerInput.js +3 -4
- package/build/components/DatePickerInput/DatePickerInput.props.d.ts +6 -0
- package/build/components/DescriptionList/DescriptionList.d.ts +1 -1
- package/build/components/DescriptionList/DescriptionList.js +2 -2
- package/build/components/DescriptionList/DescriptionList.props.d.ts +1 -0
- package/build/components/DescriptionList/DescriptionListItem.d.ts +1 -1
- package/build/components/DescriptionList/DescriptionListItem.js +3 -2
- package/build/components/DescriptionList/DescriptionListItem.props.d.ts +1 -0
- package/build/components/FormField/FormField.context.d.ts +8 -2
- package/build/components/FormField/FormField.d.ts +1 -1
- package/build/components/FormField/FormField.js +24 -4
- package/build/components/FormField/FormField.props.d.ts +2 -0
- package/build/components/FormField/FormFieldLabel.d.ts +1 -1
- package/build/components/FormField/FormFieldLabel.js +3 -3
- package/build/components/FormField/FormFieldValid.js +2 -2
- package/build/components/Input/Input.js +48 -10
- package/build/components/Input/Input.props.d.ts +7 -1
- package/build/components/Label/Label.d.ts +1 -1
- package/build/components/Label/Label.js +5 -1
- package/build/components/Label/Label.props.d.ts +3 -2
- package/build/components/Radio/RadioGroup.d.ts +1 -1
- package/build/components/Radio/RadioGroup.js +2 -2
- package/build/components/Radio/RadioGroup.props.d.ts +1 -0
- package/build/components/RadioCard/RadioCard.d.ts +1 -1
- package/build/components/RadioCard/RadioCard.js +2 -2
- package/build/components/RadioCard/RadioCard.props.d.ts +1 -0
- package/build/components/Select/Select.d.ts +1 -1
- package/build/components/Select/Select.js +2 -2
- package/build/components/Select/Select.props.d.ts +10 -0
- package/build/components/Switch/Switch.js +1 -1
- package/build/components/Tabs/Tabs.d.ts +1 -1
- package/build/components/Tabs/Tabs.js +1 -1
- package/build/components/Textarea/Textarea.d.ts +1 -1
- package/build/components/Textarea/Textarea.js +46 -6
- package/build/components/Textarea/Textarea.props.d.ts +8 -0
- package/build/components/Toast/ToastItem.js +1 -1
- package/build/components/ToggleButton/ToggleButtonIcon.js +1 -1
- package/build/components/ToggleButton/ToggleButtonRoot.js +0 -2
- package/build/components/UnstyledIconButton/UnstyledIconButtonIcon.js +1 -1
- package/build/components/VerificationInput/VerificationInput.d.ts +1 -1
- package/build/components/VerificationInput/VerificationInput.js +2 -2
- package/build/components/VerificationInput/VerificationInput.props.d.ts +4 -0
- package/build/utils/coloursAsArray.js +1 -1
- package/docs/components/AllComponents.web.tsx +19 -20
- package/docs/components/UsageWrap.tsx +17 -20
- package/docs/theme-tokens.mdx +390 -2
- package/eslint.config.js +5 -1
- package/package.json +12 -12
- package/src/components/Accordion/Accordion.figma.tsx +15 -17
- package/src/components/Accordion/AccordionItem.figma.tsx +27 -0
- package/src/components/Avatar/Avatar.figma.tsx +11 -21
- package/src/components/Avatar/Avatar.tsx +0 -2
- package/src/components/Badge/Badge.figma.tsx +45 -54
- package/src/components/Banner/Banner.figma.tsx +21 -13
- package/src/components/Banner/Banner.stories.tsx +4 -4
- package/src/components/Banner/Banner.tsx +2 -1
- package/src/components/Button/Button.figma.tsx +118 -46
- package/src/components/Card/Card.figma.tsx +27 -43
- package/src/components/Card/Card.stories.tsx +1 -1
- package/src/components/Carousel/Carousel.figma.tsx +20 -17
- package/src/components/Carousel/Carousel.tsx +1 -1
- package/src/components/Checkbox/Checkbox.docs.mdx +32 -31
- package/src/components/Checkbox/Checkbox.figma.tsx +15 -18
- package/src/components/Checkbox/Checkbox.stories.tsx +2 -2
- package/src/components/Checkbox/CheckboxGroup.figma.tsx +48 -15
- package/src/components/Checkbox/CheckboxGroup.props.ts +2 -1
- package/src/components/Checkbox/CheckboxGroup.tsx +6 -1
- package/src/components/Checkbox/CheckboxTileRoot.figma.tsx +24 -27
- package/src/components/CurrencyInput/CurrencyInput.docs.mdx +52 -9
- package/src/components/CurrencyInput/CurrencyInput.figma.tsx +65 -49
- package/src/components/CurrencyInput/CurrencyInput.props.ts +6 -0
- package/src/components/CurrencyInput/CurrencyInput.stories.tsx +30 -1
- package/src/components/CurrencyInput/CurrencyInput.tsx +16 -8
- package/src/components/DateInput/DateInput.figma.tsx +58 -45
- package/src/components/DateInput/DateInput.tsx +1 -0
- package/src/components/DateInput/DateInputSegment.tsx +2 -3
- package/src/components/DatePicker/DatePicker.figma.tsx +47 -0
- package/src/components/DatePicker/DatePicker.tsx +8 -4
- package/src/components/DatePicker/DatePickerHeader/DatePickerHeader.props.ts +0 -2
- package/src/components/DatePicker/DatePickerHeader/index.tsx +2 -2
- package/src/components/DatePicker/index.ts +2 -0
- package/src/components/DatePicker/polyfill.ts +3 -3
- package/src/components/DatePicker/time-picker/wheel-web.tsx +0 -1
- package/src/components/DatePickerInput/DatePickerInput.docs.mdx +22 -0
- package/src/components/DatePickerInput/DatePickerInput.figma.tsx +18 -46
- package/src/components/DatePickerInput/DatePickerInput.props.ts +6 -0
- package/src/components/DatePickerInput/DatePickerInput.tsx +17 -5
- package/src/components/DescriptionList/DescriptionList.docs.mdx +16 -14
- package/src/components/DescriptionList/DescriptionList.figma.tsx +41 -17
- package/src/components/DescriptionList/DescriptionList.props.ts +1 -0
- package/src/components/DescriptionList/DescriptionList.stories.tsx +24 -0
- package/src/components/DescriptionList/DescriptionList.tsx +2 -0
- package/src/components/DescriptionList/DescriptionListItem.figma.tsx +42 -0
- package/src/components/DescriptionList/DescriptionListItem.props.ts +1 -0
- package/src/components/DescriptionList/DescriptionListItem.tsx +7 -0
- package/src/components/Divider/Divider.figma.tsx +10 -23
- package/src/components/FormField/FormField.context.ts +6 -1
- package/src/components/FormField/FormField.docs.mdx +30 -30
- package/src/components/FormField/FormField.props.ts +2 -0
- package/src/components/FormField/FormField.stories.tsx +8 -2
- package/src/components/FormField/FormField.tsx +38 -4
- package/src/components/FormField/FormFieldLabel.tsx +7 -3
- package/src/components/FormField/FormFieldValid.tsx +2 -2
- package/src/components/Input/Input.docs.mdx +67 -22
- package/src/components/Input/Input.props.ts +7 -1
- package/src/components/Input/Input.stories.tsx +9 -1
- package/src/components/Input/Input.tsx +124 -60
- package/src/components/Label/Label.props.ts +3 -2
- package/src/components/Label/Label.tsx +11 -1
- package/src/components/List/List.stories.tsx +1 -4
- package/src/components/Radio/Radio.docs.mdx +31 -30
- package/src/components/Radio/Radio.stories.tsx +1 -1
- package/src/components/Radio/RadioGroup.props.ts +1 -0
- package/src/components/Radio/RadioGroup.stories.tsx +6 -0
- package/src/components/Radio/RadioGroup.tsx +6 -1
- package/src/components/RadioCard/RadioCard.docs.mdx +31 -30
- package/src/components/RadioCard/RadioCard.props.ts +1 -0
- package/src/components/RadioCard/RadioCard.tsx +8 -2
- package/src/components/Select/Select.props.ts +10 -0
- package/src/components/Select/Select.tsx +3 -2
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +0 -1
- package/src/components/Textarea/Textarea.docs.mdx +65 -17
- package/src/components/Textarea/Textarea.props.ts +8 -0
- package/src/components/Textarea/Textarea.stories.tsx +23 -2
- package/src/components/Textarea/Textarea.tsx +87 -19
- package/src/components/ThemedImage/ThemedImage.stories.tsx +14 -14
- package/src/components/Toast/ToastItem.tsx +1 -1
- package/src/components/ToggleButton/ToggleButtonIcon.tsx +1 -1
- package/src/components/ToggleButton/ToggleButtonRoot.tsx +0 -2
- package/src/components/UnstyledIconButton/UnstyledIconButtonIcon.tsx +1 -1
- package/src/components/VerificationInput/VerificationInput.docs.mdx +1 -0
- package/src/components/VerificationInput/VerificationInput.props.ts +4 -1
- package/src/components/VerificationInput/VerificationInput.tsx +2 -0
- package/src/utils/coloursAsArray.ts +1 -1
- package/tsconfig.eslint.json +13 -0
- package/src/components/Accordion/AccordionItemRoot.figma.tsx +0 -47
- package/src/components/DatePicker/DatePickerCalendar.figma.tsx +0 -34
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import { DescriptionListItem } from '../';
|
|
3
|
+
|
|
4
|
+
figma.connect(
|
|
5
|
+
DescriptionListItem,
|
|
6
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=7247-5209&t=3uUSBVdxldgG5uz3-4',
|
|
7
|
+
{
|
|
8
|
+
props: {
|
|
9
|
+
heading: figma.string('Heading'),
|
|
10
|
+
direction: figma.enum('Direction', {
|
|
11
|
+
Row: 'row',
|
|
12
|
+
Column: 'column',
|
|
13
|
+
}),
|
|
14
|
+
description: figma.boolean('Description?', {
|
|
15
|
+
true: figma.string('Description'),
|
|
16
|
+
}),
|
|
17
|
+
trailingContent: figma.boolean('Trailing content?', {
|
|
18
|
+
true: figma.nestedProps('Trailing content', {
|
|
19
|
+
trailingContent: figma.instance('Variant'),
|
|
20
|
+
}),
|
|
21
|
+
}),
|
|
22
|
+
invalidText: figma.enum('State', {
|
|
23
|
+
Invalid: figma.nestedProps('Validation Text', {
|
|
24
|
+
invalidText: figma.string('Text'),
|
|
25
|
+
}),
|
|
26
|
+
}),
|
|
27
|
+
numericValue: figma.boolean('Numerical value?', {
|
|
28
|
+
true: figma.string('Numerical value'),
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
example: props => (
|
|
32
|
+
<DescriptionListItem
|
|
33
|
+
heading={props.heading}
|
|
34
|
+
description={props.description}
|
|
35
|
+
direction={props.direction}
|
|
36
|
+
trailingContent={props.trailingContent?.trailingContent}
|
|
37
|
+
invalidText={props.invalidText?.invalidText}
|
|
38
|
+
numericValue={props.numericValue}
|
|
39
|
+
/>
|
|
40
|
+
),
|
|
41
|
+
}
|
|
42
|
+
);
|
|
@@ -3,6 +3,7 @@ import { View } from 'react-native';
|
|
|
3
3
|
import { StyleSheet } from 'react-native-unistyles';
|
|
4
4
|
import { useTheme } from '../../hooks';
|
|
5
5
|
import { BodyText } from '../BodyText';
|
|
6
|
+
import { DetailText } from '../DetailText';
|
|
6
7
|
import Helper from '../Helper/Helper';
|
|
7
8
|
import { useDescriptionListContext } from './DescriptionList.context';
|
|
8
9
|
import type DescriptionListItemProps from './DescriptionListItem.props';
|
|
@@ -13,6 +14,7 @@ const DescriptionListItem = ({
|
|
|
13
14
|
headingWidth,
|
|
14
15
|
trailingContent,
|
|
15
16
|
invalidText,
|
|
17
|
+
numericValue,
|
|
16
18
|
style,
|
|
17
19
|
...props
|
|
18
20
|
}: DescriptionListItemProps) => {
|
|
@@ -51,6 +53,11 @@ const DescriptionListItem = ({
|
|
|
51
53
|
/>
|
|
52
54
|
)}
|
|
53
55
|
</View>
|
|
56
|
+
{numericValue ? (
|
|
57
|
+
<View style={styles.descriptionWrapper}>
|
|
58
|
+
<DetailText size="lg">{numericValue}</DetailText>
|
|
59
|
+
</View>
|
|
60
|
+
) : null}
|
|
54
61
|
</View>
|
|
55
62
|
{trailingContent ? trailingContent : null}
|
|
56
63
|
</View>
|
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Divider from
|
|
3
|
-
import figma from "@figma/code-connect"
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import Divider from './Divider';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
figma.connect(
|
|
13
|
-
Divider,
|
|
14
|
-
"https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=2421%3A1687",
|
|
15
|
-
{
|
|
16
|
-
props: {
|
|
17
|
-
// These props were automatically mapped based on your linked code:
|
|
18
|
-
orientation: figma.enum("Orientation", {
|
|
19
|
-
Horizontal: "horizontal",
|
|
20
|
-
Vertical: "vertical",
|
|
21
|
-
}),
|
|
22
|
-
},
|
|
23
|
-
example: (props) => <Divider orientation={props.orientation} />,
|
|
4
|
+
figma.connect(Divider, 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=2421%3A1687', {
|
|
5
|
+
props: {
|
|
6
|
+
orientation: figma.enum('Orientation', {
|
|
7
|
+
Horizontal: 'horizontal',
|
|
8
|
+
Vertical: 'vertical',
|
|
9
|
+
}),
|
|
24
10
|
},
|
|
25
|
-
|
|
11
|
+
example: props => <Divider orientation={props.orientation} />,
|
|
12
|
+
});
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { createContext, useContext } from 'react';
|
|
2
2
|
import { FormFieldBaseProps } from './FormField.props';
|
|
3
3
|
|
|
4
|
-
export const FormFieldContext = createContext<
|
|
4
|
+
export const FormFieldContext = createContext<
|
|
5
|
+
FormFieldBaseProps & {
|
|
6
|
+
setShouldHandleAccessibility?: (value: boolean) => void;
|
|
7
|
+
shouldHandleAccessibility?: boolean;
|
|
8
|
+
}
|
|
9
|
+
>({});
|
|
5
10
|
|
|
6
11
|
export const useFormFieldContext = () => useContext(FormFieldContext);
|
|
@@ -1,32 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { Canvas, Controls, Meta, Story } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { EmailMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
InputField,
|
|
4
|
+
Center,
|
|
6
5
|
FormField,
|
|
7
6
|
FormFieldHelper,
|
|
8
7
|
FormFieldHelperText,
|
|
9
|
-
FormFieldLabel,
|
|
10
|
-
FormFieldLabelText,
|
|
11
|
-
FormFieldInvalidIcon,
|
|
12
8
|
FormFieldInvalid,
|
|
9
|
+
FormFieldInvalidIcon,
|
|
13
10
|
FormFieldInvalidText,
|
|
14
|
-
|
|
11
|
+
FormFieldLabel,
|
|
12
|
+
FormFieldLabelText,
|
|
13
|
+
FormFieldTextContent,
|
|
15
14
|
FormFieldValid,
|
|
15
|
+
FormFieldValidIcon,
|
|
16
16
|
FormFieldValidText,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
RadioGroup,
|
|
17
|
+
Input,
|
|
18
|
+
InputField,
|
|
20
19
|
Radio,
|
|
20
|
+
RadioGroup,
|
|
21
21
|
RadioIndicator,
|
|
22
22
|
RadioLabel,
|
|
23
|
-
// Checkbox,
|
|
24
|
-
// CheckboxIndicator,
|
|
25
|
-
// CheckboxIcon,
|
|
26
|
-
// CheckboxLabel,
|
|
27
23
|
} from '../../';
|
|
28
|
-
import {
|
|
29
|
-
import
|
|
24
|
+
import { BackToTopButton, UsageWrap, ViewFigmaButton } from '../../../docs/components';
|
|
25
|
+
import * as Stories from './FormField.stories';
|
|
30
26
|
|
|
31
27
|
<Meta title="Forms / Form Field" />
|
|
32
28
|
|
|
@@ -116,19 +112,23 @@ const MyComponent = () => {
|
|
|
116
112
|
|
|
117
113
|
## Props
|
|
118
114
|
|
|
119
|
-
| Name
|
|
120
|
-
|
|
|
121
|
-
| `validationStatus`
|
|
122
|
-
| `disabled`
|
|
123
|
-
| `readonly`
|
|
124
|
-
| `label`
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
115
|
+
| Name | Type | Default | Description |
|
|
116
|
+
| ---------------------------------- | ----------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------- |
|
|
117
|
+
| `validationStatus` | `'initial' \| 'valid' \| 'invalid'` | `'initial'` | The validation status of the field. |
|
|
118
|
+
| `disabled` | `boolean` | `false` | Whether the field is disabled. |
|
|
119
|
+
| `readonly` | `boolean` | `false` | Whether the field is readonly. |
|
|
120
|
+
| `label` | `string` | `-` | The label for the field. |
|
|
121
|
+
| `labelVariant` | `'heading' \| 'body'` | `'body'` | The variant of the label text. |
|
|
122
|
+
| `helperText` | `string` | `-` | The helper text for the field. |
|
|
123
|
+
| `helperIcon` | `React.ComponentType` | `-` | The icon for the helper text. |
|
|
124
|
+
| `helperPosition` | `'top' \| 'bottom'` | `'top'` | The position of the helper text. |
|
|
125
|
+
| `validText` | `string` | `-` | The valid text for the field. |
|
|
126
|
+
| `invalidText` | `string` | `-` | The invalid text for the field. |
|
|
127
|
+
| `showValidationIcon` | `boolean` | `false` | Whether to show the validation icon next to the validation text. |
|
|
128
|
+
| `required` | `boolean` | `true` | Whether the field is required. |
|
|
129
|
+
| `accessibilityHandledByChildren`\* | `boolean` | `false` | Whether accessibility is handled by child components. (Hides accessibility for the FormField itself) |
|
|
130
|
+
|
|
131
|
+
- This prop is useful when the child component (e.g., Input) manages its own accessibility attributes, preventing screen readers from reading the FormField's label and helper text multiple times.
|
|
132
132
|
|
|
133
133
|
## Components
|
|
134
134
|
|
|
@@ -6,11 +6,13 @@ export interface FormFieldBaseProps {
|
|
|
6
6
|
disabled?: boolean;
|
|
7
7
|
readonly?: boolean;
|
|
8
8
|
label?: string;
|
|
9
|
+
labelVariant?: 'heading' | 'body';
|
|
9
10
|
helperText?: string;
|
|
10
11
|
helperIcon?: ComponentType;
|
|
11
12
|
validText?: string;
|
|
12
13
|
invalidText?: string;
|
|
13
14
|
required?: boolean;
|
|
15
|
+
accessibilityHandledByChildren?: boolean;
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
interface FormFieldProps extends FormFieldBaseProps, ViewProps {}
|
|
@@ -28,6 +28,12 @@ const meta = {
|
|
|
28
28
|
description: 'The label of the Input component',
|
|
29
29
|
defaultValue: 'Label',
|
|
30
30
|
},
|
|
31
|
+
labelVariant: {
|
|
32
|
+
control: 'radio',
|
|
33
|
+
options: ['heading', 'body'],
|
|
34
|
+
description: 'The label variant of the Input component',
|
|
35
|
+
defaultValue: 'body',
|
|
36
|
+
},
|
|
31
37
|
helperText: {
|
|
32
38
|
control: 'text',
|
|
33
39
|
description: 'The helper text of the Input component',
|
|
@@ -37,7 +43,7 @@ const meta = {
|
|
|
37
43
|
control: 'select',
|
|
38
44
|
options: ['none', ...Object.keys(Icons).filter(icon => icon.includes('Medium'))],
|
|
39
45
|
description: 'The helper text icon of the Input component',
|
|
40
|
-
defaultValue: '
|
|
46
|
+
defaultValue: 'none',
|
|
41
47
|
},
|
|
42
48
|
|
|
43
49
|
validText: {
|
|
@@ -55,9 +61,9 @@ const meta = {
|
|
|
55
61
|
validationStatus: 'initial',
|
|
56
62
|
disabled: false,
|
|
57
63
|
label: 'Label',
|
|
64
|
+
labelVariant: 'body',
|
|
58
65
|
helperText: 'Helper text',
|
|
59
66
|
helperIcon: undefined,
|
|
60
|
-
|
|
61
67
|
validText: 'Valid text',
|
|
62
68
|
invalidText: 'Invalid error text',
|
|
63
69
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createFormControl } from '@gluestack-ui/form-control';
|
|
2
|
-
import { useMemo } from 'react';
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
4
|
import { HelperIcon, HelperText } from '../Helper';
|
|
5
5
|
import { FormFieldContext } from './FormField.context';
|
|
@@ -46,16 +46,40 @@ const FormField = ({
|
|
|
46
46
|
validText,
|
|
47
47
|
invalidText,
|
|
48
48
|
required = true,
|
|
49
|
+
labelVariant = 'body',
|
|
50
|
+
accessibilityHandledByChildren = false,
|
|
49
51
|
...props
|
|
50
52
|
}: FormFieldProps) => {
|
|
53
|
+
const [shouldHandleAccessibility, setShouldHandleAccessibility] = useState<boolean>(
|
|
54
|
+
accessibilityHandledByChildren
|
|
55
|
+
);
|
|
51
56
|
const value = useMemo(
|
|
52
57
|
() => ({
|
|
53
58
|
validationStatus,
|
|
54
59
|
disabled,
|
|
55
60
|
readonly,
|
|
56
61
|
required,
|
|
62
|
+
label,
|
|
63
|
+
helperText,
|
|
64
|
+
helperIcon,
|
|
65
|
+
validText,
|
|
66
|
+
invalidText,
|
|
67
|
+
setShouldHandleAccessibility,
|
|
68
|
+
shouldHandleAccessibility,
|
|
57
69
|
}),
|
|
58
|
-
[
|
|
70
|
+
[
|
|
71
|
+
validationStatus,
|
|
72
|
+
disabled,
|
|
73
|
+
readonly,
|
|
74
|
+
required,
|
|
75
|
+
label,
|
|
76
|
+
helperText,
|
|
77
|
+
helperIcon,
|
|
78
|
+
validText,
|
|
79
|
+
invalidText,
|
|
80
|
+
setShouldHandleAccessibility,
|
|
81
|
+
shouldHandleAccessibility,
|
|
82
|
+
]
|
|
59
83
|
);
|
|
60
84
|
|
|
61
85
|
return (
|
|
@@ -64,13 +88,23 @@ const FormField = ({
|
|
|
64
88
|
{(!!label || !!helperText) && (
|
|
65
89
|
<FormFieldTextContent>
|
|
66
90
|
{!!label && (
|
|
67
|
-
<FormFieldLabelText
|
|
91
|
+
<FormFieldLabelText
|
|
92
|
+
variant={labelVariant}
|
|
93
|
+
importantForAccessibility={shouldHandleAccessibility ? 'no' : undefined}
|
|
94
|
+
accessibilityElementsHidden={shouldHandleAccessibility}
|
|
95
|
+
>
|
|
68
96
|
{label}
|
|
69
97
|
{!required ? ` (Optional)` : ''}
|
|
70
98
|
</FormFieldLabelText>
|
|
71
99
|
)}
|
|
72
100
|
{!!helperText && (
|
|
73
|
-
<FormFieldHelper
|
|
101
|
+
<FormFieldHelper
|
|
102
|
+
text={helperText}
|
|
103
|
+
icon={helperIcon}
|
|
104
|
+
showIcon={!!helperIcon}
|
|
105
|
+
importantForAccessibility={shouldHandleAccessibility ? 'no' : undefined}
|
|
106
|
+
accessibilityElementsHidden={shouldHandleAccessibility}
|
|
107
|
+
/>
|
|
74
108
|
)}
|
|
75
109
|
</FormFieldTextContent>
|
|
76
110
|
)}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { useFormFieldContext } from './FormField.context';
|
|
2
1
|
import { Label } from '../Label';
|
|
3
2
|
import LabelProps from '../Label/Label.props';
|
|
3
|
+
import { useFormFieldContext } from './FormField.context';
|
|
4
4
|
|
|
5
|
-
const FormFieldLabel = ({ children }: Omit<LabelProps, 'disabled'>) => {
|
|
5
|
+
const FormFieldLabel = ({ children, ...props }: Omit<LabelProps, 'disabled'>) => {
|
|
6
6
|
const { disabled } = useFormFieldContext();
|
|
7
|
-
return
|
|
7
|
+
return (
|
|
8
|
+
<Label disabled={disabled} {...props}>
|
|
9
|
+
{children}
|
|
10
|
+
</Label>
|
|
11
|
+
);
|
|
8
12
|
};
|
|
9
13
|
|
|
10
14
|
FormFieldLabel.displayName = 'FormFieldLabel';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TickCircleSmallIcon } from '@utilitywarehouse/hearth-react-native-icons';
|
|
2
2
|
import { Helper } from '../Helper';
|
|
3
3
|
import HelperProps from '../Helper/Helper.props';
|
|
4
|
-
import {
|
|
4
|
+
import { useFormFieldContext } from './FormField.context';
|
|
5
5
|
|
|
6
6
|
const FormFieldValid = ({
|
|
7
7
|
children,
|
|
@@ -83,18 +83,25 @@ all of the React Native [`View` props](https://reactnative.dev/docs/view).
|
|
|
83
83
|
| ---------------- | ---------------------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
84
84
|
| type | `'text' \| 'password'` | `'text'` | The type of the input. |
|
|
85
85
|
| validationStatus | `'initial' \| 'valid' \| 'invalid` | `'initial'` | The validation status of the input. |
|
|
86
|
-
| disabled | boolean
|
|
87
|
-
| readonly | boolean
|
|
88
|
-
| focused | boolean
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
|
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
97
|
-
|
|
|
86
|
+
| disabled | `boolean` | `false` | Disables the input. |
|
|
87
|
+
| readonly | `boolean` | `false` | Makes the input read-only. |
|
|
88
|
+
| focused | `boolean` | `false` | Sets focus on the input. |
|
|
89
|
+
| label | `string` | `-` | The label for the input. **(Only to be used if the input has no children)** |
|
|
90
|
+
| labelVariant | `'heading' \| 'body'` | `'body'` | The variant of the label text. **(Only to be used if the input has no children)** |
|
|
91
|
+
| helperText | `string` | `-` | Helper text to display below the input. **(Only to be used if the input has no children)** |
|
|
92
|
+
| helperIcon | `React.ComponentType` | `-` | Icon to display alongside the helper text. **(Only to be used if the input has no children)** |
|
|
93
|
+
| validText | `string` | `-` | Text to display when validation status is 'valid'. **(Only to be used if the input has no children)** |
|
|
94
|
+
| invalidText | `string` | `-` | Text to display when validation status is 'invalid'. **(Only to be used if the input has no children)** |
|
|
95
|
+
| required | `boolean` | `true` | Indicates that the input is required. **(Only to be used if the input has no children)** |
|
|
96
|
+
| leadingIcon | `React.ComponentType` | `-` | The leading icon of the input. **(Only to be used if the input has no children)** |
|
|
97
|
+
| trailingIcon | `React.ComponentType` | `-` | The trailing icon of the input. **(Only to be used if the input has no children)** |
|
|
98
|
+
| value | `string` | `-` | The value of the input. **(Only to be used if the input has no children)** |
|
|
99
|
+
| onChange | `function` | `-` | Callback function that is triggered when the input value changes. **(Only to be used if the input has no children)** **(Only to be used if the input has no children)** |
|
|
100
|
+
| onBlur | `function` | `-` | Callback function that is triggered when the input loses focus. **(Only to be used if the input has no children)** |
|
|
101
|
+
| onFocus | `function` | `-` | Callback function that is triggered when the input gains focus. **(Only to be used if the input has no children)** |
|
|
102
|
+
| placeholder | `string` | `-` | The placeholder text for the input. **(Only to be used if the input has no children)** |
|
|
103
|
+
| required | `boolean` | `true` | Indicates that the input is required. **(Only to be used if the input has no children)** |
|
|
104
|
+
| inBottomSheet | `boolean` | `false` | Indicates if the input is within a bottom sheet. |
|
|
98
105
|
|
|
99
106
|
If the `leadingIcon` or `trailingIcon` props are used, the `Input` component should not have any children.
|
|
100
107
|
|
|
@@ -105,19 +112,19 @@ The `InputField` inherits all of the React Native [`TextInput` props](https://re
|
|
|
105
112
|
| Prop | Type | Default | Description |
|
|
106
113
|
| ------------- | ---------------------- | -------- | ----------------------------------------------------------------- |
|
|
107
114
|
| type | `'text' \| 'password'` | `'text'` | The type of the input. |
|
|
108
|
-
| value | string
|
|
109
|
-
| onChange | function
|
|
110
|
-
| onBlur | function
|
|
111
|
-
| onFocus | function
|
|
112
|
-
| placeholder | string
|
|
113
|
-
| required | boolean
|
|
114
|
-
| inBottomSheet | boolean
|
|
115
|
+
| value | `string` | `-` | The value of the input. |
|
|
116
|
+
| onChange | `function` | `-` | Callback function that is triggered when the input value changes. |
|
|
117
|
+
| onBlur | `function` | `-` | Callback function that is triggered when the input loses focus. |
|
|
118
|
+
| onFocus | `function` | `-` | Callback function that is triggered when the input gains focus. |
|
|
119
|
+
| placeholder | `string` | `-` | The placeholder text for the input. |
|
|
120
|
+
| required | `boolean` | `true` | Indicates that the input is required. |
|
|
121
|
+
| inBottomSheet | `boolean` | `false` | Indicates if the input is within a bottom sheet. |
|
|
115
122
|
|
|
116
123
|
### `InputIcon`
|
|
117
124
|
|
|
118
|
-
| Prop | Type
|
|
119
|
-
| ---- |
|
|
120
|
-
| as | string | | The icon component. |
|
|
125
|
+
| Prop | Type | Default | Description |
|
|
126
|
+
| ---- | -------- | ------- | ------------------- |
|
|
127
|
+
| as | `string` | | The icon component. |
|
|
121
128
|
|
|
122
129
|
### `InputSlot`
|
|
123
130
|
|
|
@@ -191,6 +198,41 @@ The `Input` component has the following variants:
|
|
|
191
198
|
|
|
192
199
|
## Examples
|
|
193
200
|
|
|
201
|
+
## With Label and Helper Text
|
|
202
|
+
|
|
203
|
+
The `Input` component can be used with a label and helper text by passing the `label` and `helperText` props.
|
|
204
|
+
|
|
205
|
+
<UsageWrap>
|
|
206
|
+
<Center>
|
|
207
|
+
<Input
|
|
208
|
+
label="Label"
|
|
209
|
+
helperText="Helper text"
|
|
210
|
+
onChange={() => console.log('###')}
|
|
211
|
+
placeholder="Placeholder"
|
|
212
|
+
/>
|
|
213
|
+
</Center>
|
|
214
|
+
</UsageWrap>
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
import { Input } from '@utilitywarehouse/hearth-react-native';
|
|
218
|
+
|
|
219
|
+
const MyComponent = () => {
|
|
220
|
+
const [value, setValue] = useState('');
|
|
221
|
+
const handleChange = e => {
|
|
222
|
+
setValue(e.target.value);
|
|
223
|
+
};
|
|
224
|
+
return (
|
|
225
|
+
<Input
|
|
226
|
+
label="Label"
|
|
227
|
+
helperText="Helper text"
|
|
228
|
+
onChange={handleChange}
|
|
229
|
+
value={value}
|
|
230
|
+
placeholder="Placeholder"
|
|
231
|
+
/>
|
|
232
|
+
);
|
|
233
|
+
};
|
|
234
|
+
```
|
|
235
|
+
|
|
194
236
|
### With `FormField`
|
|
195
237
|
|
|
196
238
|
The `Input` component can be used with the `FormField` component to create a custom input field.
|
|
@@ -230,6 +272,9 @@ We have outlined the various features that ensure the Input component is accessi
|
|
|
230
272
|
|
|
231
273
|
### Screen Reader
|
|
232
274
|
|
|
275
|
+
- When setting the label prop, it is associated with the Input using aria-label.
|
|
276
|
+
- When setting the helperText prop, it is associated with the Input using aria-describedby.
|
|
277
|
+
- The required prop to indicate if the Input is required or optional and is read out by screen readers.
|
|
233
278
|
- Compatible with screen readers such as VoiceOver and Talk-back.
|
|
234
279
|
- The accessible and aria-label props to provide descriptive information about the Input
|
|
235
280
|
- Setting aria-traits and aria-hint to provide contextual information about the various states of the Input, such as "double tap to edit".
|
|
@@ -27,6 +27,13 @@ export interface InputBaseProps {
|
|
|
27
27
|
focused?: boolean;
|
|
28
28
|
placeholder?: string;
|
|
29
29
|
inBottomSheet?: boolean;
|
|
30
|
+
label?: string;
|
|
31
|
+
labelVariant?: 'heading' | 'body';
|
|
32
|
+
helperText?: string;
|
|
33
|
+
helperIcon?: ComponentType;
|
|
34
|
+
validText?: string;
|
|
35
|
+
invalidText?: string;
|
|
36
|
+
required?: boolean;
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
// For inputs that have children
|
|
@@ -40,7 +47,6 @@ export interface InputWithChildrenProps extends InputBaseProps, ViewProps {
|
|
|
40
47
|
onClear?: never;
|
|
41
48
|
leadingIcon?: never;
|
|
42
49
|
trailingIcon?: never;
|
|
43
|
-
required?: never;
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
// Base for inputs without children
|
|
@@ -82,7 +82,15 @@ export const Playground: Story = {
|
|
|
82
82
|
const leadingIcon = leading === 'none' ? undefined : Icons[leading];
|
|
83
83
|
// @ts-expect-error - This is a playground
|
|
84
84
|
const trailingIcon = trailing === 'none' ? undefined : Icons[trailing];
|
|
85
|
-
return
|
|
85
|
+
return (
|
|
86
|
+
<Input
|
|
87
|
+
{...args}
|
|
88
|
+
leadingIcon={leadingIcon}
|
|
89
|
+
trailingIcon={trailingIcon}
|
|
90
|
+
label="First Name"
|
|
91
|
+
helperText="Only enter your first name, not your full name"
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
86
94
|
},
|
|
87
95
|
};
|
|
88
96
|
|