mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Update TextFieldBase
to include InputComponent prop (#16422)
* Update TextFieldBase to include InputComponent * Updating docs * Adding test * Update to docs * Lint fixes * Small doc fixe to remove some unneded spaces
This commit is contained in:
parent
ce9af8aac3
commit
67e0b60dcf
@ -188,6 +188,61 @@ const handleOnChange = (e) => {
|
||||
</Box>
|
||||
```
|
||||
|
||||
### Input Component
|
||||
|
||||
Use the `InputComponent` prop change the component used for the input element. This is useful for replacing the base input with a custom input while retaining the functionality of the `TextFieldBase`.
|
||||
|
||||
Defaults to the [Text](/docs/ui-components-component-library-text-text-stories-js--default-story) component
|
||||
|
||||
To function fully the custom component should accept the following props:
|
||||
|
||||
- `aria-invalid`
|
||||
- `as`
|
||||
- `autoComplete`
|
||||
- `autoFocus`
|
||||
- `backgroundColor`
|
||||
- `defaultValue`
|
||||
- `disabled`
|
||||
- `focused`
|
||||
- `id`
|
||||
- `margin`
|
||||
- `maxLength`
|
||||
- `name`
|
||||
- `onBlur`
|
||||
- `onChange`
|
||||
- `onFocus`
|
||||
- `padding`
|
||||
- `paddingLeft`
|
||||
- `paddingRight`
|
||||
- `placeholder`
|
||||
- `readOnly`
|
||||
- `ref`
|
||||
- `required`
|
||||
- `value`
|
||||
- `variant`
|
||||
- `type`
|
||||
|
||||
<Canvas>
|
||||
<Story id="ui-components-component-library-text-field-base-text-field-base-stories-js--input-component" />
|
||||
</Canvas>
|
||||
|
||||
```jsx
|
||||
import { TextFieldBase, Icon, ICON_NAMES } from '../../ui/component-library';
|
||||
|
||||
// should map the props to the custom input component
|
||||
const CustomInputComponent = () => <div>{/* Custom input component */}</div>;
|
||||
|
||||
const TextFieldCustomInput = (args) => (
|
||||
<TextFieldBase
|
||||
size={SIZES.LG}
|
||||
InputComponent={CustomInputComponent}
|
||||
leftAccessory={
|
||||
<Icon color={COLORS.ICON_ALTERNATIVE} name={ICON_NAMES.WALLET_FILLED} />
|
||||
}
|
||||
/>
|
||||
);
|
||||
```
|
||||
|
||||
### Auto Complete
|
||||
|
||||
Use the `autoComplete` prop to set the autocomplete html attribute. It allows the browser to predict the value based on earlier typed values.
|
||||
|
@ -44,6 +44,7 @@ export const TextFieldBase = ({
|
||||
type = 'text',
|
||||
truncate = true,
|
||||
value,
|
||||
InputComponent = Text,
|
||||
...props
|
||||
}) => {
|
||||
const internalInputRef = useRef(null);
|
||||
@ -107,13 +108,13 @@ export const TextFieldBase = ({
|
||||
alignItems={ALIGN_ITEMS.CENTER}
|
||||
borderWidth={1}
|
||||
borderRadius={SIZES.SM}
|
||||
paddingLeft={4}
|
||||
paddingRight={4}
|
||||
paddingLeft={leftAccessory ? 4 : 0}
|
||||
paddingRight={rightAccessory ? 4 : 0}
|
||||
onClick={handleClick}
|
||||
{...props}
|
||||
>
|
||||
{leftAccessory}
|
||||
<Text
|
||||
<InputComponent
|
||||
aria-invalid={error}
|
||||
as="input"
|
||||
autoComplete={autoComplete ? 'on' : 'off'}
|
||||
@ -130,8 +131,8 @@ export const TextFieldBase = ({
|
||||
onChange={onChange}
|
||||
onFocus={handleFocus}
|
||||
padding={0}
|
||||
paddingLeft={leftAccessory ? 2 : null}
|
||||
paddingRight={leftAccessory ? 2 : null}
|
||||
paddingLeft={leftAccessory ? 2 : 4}
|
||||
paddingRight={rightAccessory ? 2 : 4}
|
||||
placeholder={placeholder}
|
||||
readOnly={readOnly}
|
||||
ref={handleInputRef}
|
||||
@ -179,6 +180,11 @@ TextFieldBase.propTypes = {
|
||||
* The id of the `input` element.
|
||||
*/
|
||||
id: PropTypes.string,
|
||||
/**
|
||||
* The the component that is rendered as the input
|
||||
* Defaults to the Text component
|
||||
*/
|
||||
InputComponent: PropTypes.elementType,
|
||||
/**
|
||||
* Attributes applied to the `input` element.
|
||||
*/
|
||||
|
@ -351,6 +351,90 @@ export const InputRef = (args) => {
|
||||
);
|
||||
};
|
||||
|
||||
const CustomInputComponent = ({
|
||||
as,
|
||||
autoComplete,
|
||||
autoFocus,
|
||||
defaultValue,
|
||||
disabled,
|
||||
focused,
|
||||
id,
|
||||
maxLength,
|
||||
name,
|
||||
onBlur,
|
||||
onChange,
|
||||
onFocus,
|
||||
padding,
|
||||
paddingLeft,
|
||||
paddingRight,
|
||||
placeholder,
|
||||
readOnly,
|
||||
ref,
|
||||
required,
|
||||
value,
|
||||
variant,
|
||||
type,
|
||||
className,
|
||||
'aria-invalid': ariaInvalid,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
{...{ padding, paddingLeft, paddingRight, ...props }}
|
||||
>
|
||||
<Box display={DISPLAY.INLINE_FLEX}>
|
||||
<Text
|
||||
style={{ padding: 0 }}
|
||||
aria-invalid={ariaInvalid}
|
||||
{...{
|
||||
as,
|
||||
className,
|
||||
autoComplete,
|
||||
autoFocus,
|
||||
defaultValue,
|
||||
disabled,
|
||||
focused,
|
||||
id,
|
||||
maxLength,
|
||||
name,
|
||||
onBlur,
|
||||
onChange,
|
||||
onFocus,
|
||||
placeholder,
|
||||
readOnly,
|
||||
ref,
|
||||
required,
|
||||
value,
|
||||
variant,
|
||||
type,
|
||||
}}
|
||||
/>
|
||||
<Text variant={TEXT.BODY_XS} color={COLORS.TEXT_ALTERNATIVE}>
|
||||
GoerliETH
|
||||
</Text>
|
||||
</Box>
|
||||
<Text variant={TEXT.BODY_XS}>No conversion rate available</Text>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
CustomInputComponent.propTypes = { ...TextFieldBase.propTypes };
|
||||
|
||||
export const InputComponent = (args) => (
|
||||
<TextFieldBase
|
||||
{...args}
|
||||
placeholder="0"
|
||||
type="number"
|
||||
size={SIZES.LG}
|
||||
InputComponent={CustomInputComponent}
|
||||
leftAccessory={
|
||||
<Icon color={COLORS.ICON_ALTERNATIVE} name={ICON_NAMES.WALLET_FILLED} />
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
export const AutoComplete = Template.bind({});
|
||||
AutoComplete.args = {
|
||||
autoComplete: true,
|
||||
|
@ -235,4 +235,20 @@ describe('TextFieldBase', () => {
|
||||
'',
|
||||
);
|
||||
});
|
||||
it('should render with a custom input and still work', () => {
|
||||
const CustomInputComponent = (props) => <input {...props} />;
|
||||
const { getByTestId } = render(
|
||||
<TextFieldBase
|
||||
InputComponent={CustomInputComponent}
|
||||
inputProps={{ 'data-testid': 'text-field-base', className: 'test' }}
|
||||
/>,
|
||||
);
|
||||
const textFieldBase = getByTestId('text-field-base');
|
||||
|
||||
expect(textFieldBase.value).toBe(''); // initial value is empty string
|
||||
fireEvent.change(textFieldBase, { target: { value: 'text value' } });
|
||||
expect(textFieldBase.value).toBe('text value');
|
||||
fireEvent.change(textFieldBase, { target: { value: '' } }); // reset value
|
||||
expect(textFieldBase.value).toBe(''); // value is empty string after reset
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user