diff --git a/ui/components/component-library/index.js b/ui/components/component-library/index.js
index f7d25c3ef2bf..9df42ebec4fc 100644
--- a/ui/components/component-library/index.js
+++ b/ui/components/component-library/index.js
@@ -31,7 +31,7 @@ export { PickerNetwork } from './picker-network';
export { Tag } from './tag';
export { TagUrl } from './tag-url';
export { Text, ValidTag, TextDirection, InvisibleCharacter } from './text';
-export { Input, INPUT_TYPES } from './input';
+export { Input, InputType } from './input';
export { TextField, TEXT_FIELD_TYPES, TEXT_FIELD_SIZES } from './text-field';
export { TextFieldSearch } from './text-field-search';
export { ModalContent, ModalContentSize } from './modal-content';
diff --git a/ui/components/component-library/input/README.mdx b/ui/components/component-library/input/README.mdx
index 308245a0a78a..a45c1244bcf5 100644
--- a/ui/components/component-library/input/README.mdx
+++ b/ui/components/component-library/input/README.mdx
@@ -12,7 +12,7 @@ import { Input } from './input';
## Props
-The `Input` accepts all props below as well as all [Box](/docs/components-ui-box--default-story#props) component props
+The `Input` accepts all props below as well as all [Box](/docs/components-componentlibrary-box--docs#props) component props
@@ -22,24 +22,24 @@ Use the `type` prop to change the type of input.
Possible types include:
-- `INPUT_TYPES.TEXT`
-- `INPUT_TYPES.NUMBER`
-- `INPUT_TYPES.PASSWORD`
-- `INPUT_TYPES.SEARCH`
+- `InputType.Text`
+- `InputType.Number`
+- `InputType.Password`
+- `InputType.Search`
-Defaults to `INPUT_TYPES.TEXT`.
+Defaults to `InputType.Text`.
```jsx
-import { Input, INPUT_TYPES } from '../../component-library';
+import { Input, InputType } from '../../component-library';
-
-
-
-
+
+
+
+
```
### Ref
@@ -81,9 +81,9 @@ Use the `autoComplete` prop to set the autocomplete html attribute. It allows th
```jsx
-import { Input } from '../../component-library';
+import { Input, InputType } from '../../component-library';
-;
+;
```
### Auto Focus
diff --git a/ui/components/component-library/input/__snapshots__/input.test.js.snap b/ui/components/component-library/input/__snapshots__/input.test.tsx.snap
similarity index 100%
rename from ui/components/component-library/input/__snapshots__/input.test.js.snap
rename to ui/components/component-library/input/__snapshots__/input.test.tsx.snap
diff --git a/ui/components/component-library/input/index.js b/ui/components/component-library/input/index.js
deleted file mode 100644
index a8a921a476fb..000000000000
--- a/ui/components/component-library/input/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export { Input } from './input';
-export { INPUT_TYPES } from './input.constants';
diff --git a/ui/components/component-library/input/index.ts b/ui/components/component-library/input/index.ts
new file mode 100644
index 000000000000..1d3826b99c15
--- /dev/null
+++ b/ui/components/component-library/input/index.ts
@@ -0,0 +1,4 @@
+export { Input } from './input';
+export { InputType } from './input.types';
+
+export type { InputProps } from './input.types';
diff --git a/ui/components/component-library/input/input.constants.js b/ui/components/component-library/input/input.constants.js
deleted file mode 100644
index 3d0ee82f0f54..000000000000
--- a/ui/components/component-library/input/input.constants.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export const INPUT_TYPES = {
- TEXT: 'text',
- NUMBER: 'number',
- PASSWORD: 'password',
- SEARCH: 'search',
-};
diff --git a/ui/components/component-library/input/input.js b/ui/components/component-library/input/input.js
deleted file mode 100644
index f4c7510bd803..000000000000
--- a/ui/components/component-library/input/input.js
+++ /dev/null
@@ -1,170 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classnames from 'classnames';
-
-import {
- TextVariant,
- BackgroundColor,
- BorderStyle,
-} from '../../../helpers/constants/design-system';
-
-import Box from '../../ui/box';
-
-import { Text } from '..';
-
-import { INPUT_TYPES } from './input.constants';
-
-export const Input = React.forwardRef(
- (
- {
- autoComplete,
- autoFocus,
- className,
- defaultValue,
- disabled,
- error,
- id,
- maxLength,
- name,
- onBlur,
- onChange,
- onFocus,
- placeholder,
- readOnly,
- required,
- type = 'text',
- value,
- textVariant = TextVariant.bodyMd,
- disableStateStyles,
- ...props
- },
- ref,
- ) => (
-
- ),
-);
-
-Input.propTypes = {
- /**
- * Autocomplete allows the browser to predict the value based on earlier typed values
- */
- autoComplete: PropTypes.bool,
- /**
- * If `true`, the input will be focused during the first mount.
- */
- autoFocus: PropTypes.bool,
- /**
- * An additional className to apply to the input
- */
- className: PropTypes.string,
- /**
- * The default input value, useful when not controlling the component.
- */
- defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- /**
- * If `true`, the input will be disabled.
- */
- disabled: PropTypes.bool,
- /**
- * Disables focus state by setting CSS outline: none;
- * !!IMPORTANT!!
- * If this is set to true ensure there is a proper fallback
- * to enable accessibility for keyboard only and vision impaired users
- */
- disableStateStyles: PropTypes.bool,
- /**
- * If `true`, aria-invalid will be true
- */
- error: PropTypes.bool,
- /**
- * The id of the `input` element.
- */
- id: PropTypes.string,
- /**
- * Max number of characters to allow
- */
- maxLength: PropTypes.number,
- /**
- * Name attribute of the `input` element.
- */
- name: PropTypes.string,
- /**
- * Callback fired on blur
- */
- onBlur: PropTypes.func,
- /**
- * Callback fired when the value is changed.
- */
- onChange: PropTypes.func,
- /**
- * Callback fired on focus
- */
- onFocus: PropTypes.func,
- /**
- * The short hint displayed in the input before the user enters a value.
- */
- placeholder: PropTypes.string,
- /**
- * It prevents the user from changing the value of the field (not from interacting with the field).
- */
- readOnly: PropTypes.bool,
- /**
- * If `true`, the input will be required. Currently no visual difference is shown.
- */
- required: PropTypes.bool,
- /**
- * Use this to override the text variant of the Text component.
- * Should only be used for approved custom input components
- * Use the TextVariant enum
- */
- textVariant: PropTypes.oneOf(Object.values(TextVariant)),
- /**
- * Type of the input element. Can be INPUT_TYPES.TEXT, INPUT_TYPES.PASSWORD, INPUT_TYPES.NUMBER
- * Defaults to INPUT_TYPES.TEXT ('text')
- * If you require another type add it to INPUT_TYPES
- */
- type: PropTypes.oneOf(Object.values(INPUT_TYPES)),
- /**
- * The input value, required for a controlled component.
- */
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- /**
- * Input accepts all the props from Box
- */
- ...Box.propTypes,
-};
-
-Input.displayName = 'Input';
diff --git a/ui/components/component-library/input/input.stories.js b/ui/components/component-library/input/input.stories.tsx
similarity index 84%
rename from ui/components/component-library/input/input.stories.js
rename to ui/components/component-library/input/input.stories.tsx
index 6cc5a3cf6ab4..676687350561 100644
--- a/ui/components/component-library/input/input.stories.js
+++ b/ui/components/component-library/input/input.stories.tsx
@@ -1,16 +1,16 @@
import React, { useRef } from 'react';
+import { Meta } from '@storybook/react';
import { useArgs } from '@storybook/client-api';
import {
- DISPLAY,
- FLEX_DIRECTION,
+ Display,
+ FlexDirection,
TextVariant,
} from '../../../helpers/constants/design-system';
-import Box from '../../ui/box/box';
-import { Button } from '..';
+import { Button, Box, BUTTON_VARIANT } from '..';
-import { INPUT_TYPES } from './input.constants';
+import { InputType } from './input.types';
import { Input } from './input';
import README from './README.mdx';
@@ -92,7 +92,7 @@ export default {
},
type: {
control: 'select',
- options: Object.values(INPUT_TYPES),
+ options: Object.values(InputType),
},
value: {
control: 'text',
@@ -126,7 +126,7 @@ export default {
placeholder: 'Placeholder...',
value: '',
},
-};
+} as Meta;
const Template = (args) => {
const [{ value }, updateArgs] = useArgs();
@@ -141,14 +141,14 @@ DefaultStory.storyName = 'Default';
export const Type = (args) => (
-
-
-
+
+
+
);
@@ -158,17 +158,21 @@ Type.args = {
export const Ref = (args) => {
const [{ value }, updateArgs] = useArgs();
- const inputRef = useRef(null);
+ const inputRef = useRef(null);
const handleOnClick = () => {
- inputRef.current.focus();
+ inputRef.current?.focus();
};
const handleOnChange = (e) => {
updateArgs({ value: e.target.value });
};
return (
-
+
-
@@ -178,7 +182,7 @@ export const Ref = (args) => {
export const AutoComplete = Template.bind({});
AutoComplete.args = {
autoComplete: true,
- type: INPUT_TYPES.PASSWORD,
+ type: InputType.Password,
placeholder: 'Enter password',
};
@@ -201,8 +205,9 @@ MaxLength.args = { maxLength: 10, placeholder: 'Max length 10' };
export const ReadOnly = Template.bind({});
ReadOnly.args = { readOnly: true, value: 'Read only' };
-export const Required = Template.bind({});
-Required.args = { required: true, placeholder: 'Required' };
+export const RequiredStory = Template.bind({});
+RequiredStory.args = { required: true, placeholder: 'Required' };
+RequiredStory.storyName = 'Required';
export const DisableStateStyles = Template.bind({});
DisableStateStyles.args = {
@@ -216,8 +221,8 @@ export const TextVariantStory = (args) => {
};
return (
{
it('should render correctly', () => {
@@ -72,9 +72,9 @@ describe('Input', () => {
const { getByTestId } = render(
<>
-
-
-
+
+
+
>,
);
expect(getByTestId('input-text-default')).toHaveAttribute('type', 'text');
diff --git a/ui/components/component-library/input/input.tsx b/ui/components/component-library/input/input.tsx
new file mode 100644
index 000000000000..5ff59c7a696b
--- /dev/null
+++ b/ui/components/component-library/input/input.tsx
@@ -0,0 +1,76 @@
+import React from 'react';
+import classnames from 'classnames';
+
+import {
+ TextVariant,
+ BackgroundColor,
+ BorderStyle,
+} from '../../../helpers/constants/design-system';
+
+import { Text, TextProps } from '../text';
+import { PolymorphicRef } from '../box';
+import { InputProps, InputType, InputComponent } from './input.types';
+
+export const Input: InputComponent = React.forwardRef(
+ (
+ {
+ autoComplete,
+ autoFocus,
+ className = '',
+ defaultValue,
+ disabled,
+ error,
+ id,
+ maxLength,
+ name,
+ onBlur,
+ onChange,
+ onFocus,
+ placeholder,
+ readOnly,
+ required,
+ type = InputType.Text,
+ value,
+ textVariant = TextVariant.bodyMd,
+ disableStateStyles,
+ ...props
+ }: InputProps,
+ ref: PolymorphicRef,
+ ) => (
+ )}
+ />
+ ),
+);
diff --git a/ui/components/component-library/input/input.types.ts b/ui/components/component-library/input/input.types.ts
new file mode 100644
index 000000000000..6d0c5fe26d40
--- /dev/null
+++ b/ui/components/component-library/input/input.types.ts
@@ -0,0 +1,107 @@
+import type {
+ StyleUtilityProps,
+ PolymorphicComponentPropWithRef,
+} from '../box';
+
+import { TextVariant } from '../../../helpers/constants/design-system';
+
+export enum InputType {
+ Text = 'text',
+ // eslint-disable-next-line @typescript-eslint/no-shadow
+ Number = 'number',
+ Password = 'password',
+ Search = 'search',
+}
+
+export interface InputStyleProps extends StyleUtilityProps {
+ /**
+ * Autocomplete allows the browser to predict the value based on earlier typed values
+ */
+ autoComplete?: boolean;
+ /**
+ * If `true`, the input will be focused during the first mount.
+ */
+ autoFocus?: boolean;
+ /**
+ * An additional className to apply to the input
+ */
+ className?: string;
+ /**
+ * The default input value, useful when not controlling the component.
+ */
+ defaultValue?: string | number;
+ /**
+ * If `true`, the input will be disabled.
+ */
+ disabled?: boolean;
+ /**
+ * Disables focus state by setting CSS outline: none;
+ * !!IMPORTANT!!
+ * If this is set to true ensure there is a proper fallback
+ * to enable accessibility for keyboard only and vision impaired users
+ */
+ disableStateStyles?: boolean;
+ /**
+ * If `true`, aria-invalid will be true
+ */
+ error?: boolean;
+ /**
+ * The id of the `input` element.
+ */
+ id?: string;
+ /**
+ * Max number of characters to allow
+ */
+ maxLength?: number;
+ /**
+ * Name attribute of the `input` element.
+ */
+ name?: string;
+ /**
+ * Callback fired on blur
+ */
+ onBlur?: () => void;
+ /**
+ * Callback fired when the value is changed.
+ */
+ onChange?: () => void;
+ /**
+ * Callback fired on focus
+ */
+ onFocus?: () => void;
+ /**
+ * The short hint displayed in the input before the user enters a value.
+ */
+ placeholder?: string;
+ /**
+ * It prevents the user from changing the value of the field (not from interacting with the field).
+ */
+ readOnly?: boolean;
+ /**
+ * If `true`, the input will be required. Currently no visual difference is shown.
+ */
+ required?: boolean;
+ /**
+ * Use this to override the text variant of the Text component.
+ * Should only be used for approved custom input components
+ * Use the TextVariant enum
+ */
+ textVariant?: TextVariant;
+ /**
+ * Type of the input element. Can be InputType.Text, InputType.Password, InputType.Number
+ * Defaults to InputType.Text ('text')
+ * If you require another type add it to InputType
+ */
+ type?: InputType;
+ /**
+ * The input value, required for a controlled component.
+ */
+ value?: string | number;
+}
+
+export type InputProps =
+ PolymorphicComponentPropWithRef;
+
+export type InputComponent = (
+ props: InputProps,
+) => React.ReactElement | null;