From 7f87fb4ece42e1ba63143369dcefa1c33c65040f Mon Sep 17 00:00:00 2001 From: Diana Nanyanzi <31903212+d-rita@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:15:12 +0300 Subject: [PATCH] feat: make input field clearable and add prefix icon (#1619) * feat: make input clearable and add prefix icon * feat: use onChange handler to clear text --- .../input/src/input-field/input-field.js | 9 +++ .../input-field/input-field.prod.stories.js | 39 ++++++++- components/input/src/input/input.js | 79 ++++++++++++++++++- components/input/types/index.d.ts | 16 ++++ 4 files changed, 140 insertions(+), 3 deletions(-) diff --git a/components/input/src/input-field/input-field.js b/components/input/src/input-field/input-field.js index 53875cbdd6..d9275dca17 100644 --- a/components/input/src/input-field/input-field.js +++ b/components/input/src/input-field/input-field.js @@ -39,6 +39,8 @@ class InputField extends React.Component { validationText, inputWidth, autoComplete, + clearable, + prefixIcon, dataTest = 'dhis2-uiwidgets-inputfield', } = this.props @@ -79,6 +81,9 @@ class InputField extends React.Component { initialFocus={initialFocus} readOnly={readOnly} autoComplete={autoComplete} + clearable={clearable} + prefixIcon={prefixIcon} + width={inputWidth} /> @@ -90,6 +95,8 @@ const InputFieldProps = { /** The [native `autocomplete` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-autocomplete) */ autoComplete: PropTypes.string, className: PropTypes.string, + /** Makes the input field clearable */ + clearable: PropTypes.bool, dataTest: PropTypes.string, /** Makes the input smaller */ dense: PropTypes.bool, @@ -115,6 +122,8 @@ const InputFieldProps = { name: PropTypes.string, /** Placeholder text for the input */ placeholder: PropTypes.string, + /** Add prefix icon */ + prefixIcon: PropTypes.element, /** Makes the input read-only */ readOnly: PropTypes.bool, /** Indicates this input is required */ diff --git a/components/input/src/input-field/input-field.prod.stories.js b/components/input/src/input-field/input-field.prod.stories.js index 63dcda1c67..faacad2633 100644 --- a/components/input/src/input-field/input-field.prod.stories.js +++ b/components/input/src/input-field/input-field.prod.stories.js @@ -1,5 +1,6 @@ import { sharedPropTypes } from '@dhis2/ui-constants' -import React from 'react' +import { IconLocation16, IconSearch16 } from '@dhis2/ui-icons' +import React, { useState } from 'react' import { InputField } from './index.js' const subtitle = 'Allows a user to enter data, usually text' @@ -156,3 +157,39 @@ ValueTextOverflow.args = { export const Required = Template.bind({}) Required.args = { required: true } + +export const InputWithPrefixIcon = (args) => ( + <> + } + /> + } + inputWidth={'200px'} + /> + +) + +export const ClearableInput = (args) => { + const [value, setValue] = useState('value') + return ( + setValue(e.value)} + clearable + clearText={() => setValue('')} + value={value} + /> + ) +} diff --git a/components/input/src/input/input.js b/components/input/src/input/input.js index 3fd5ed00c0..6f702aa3fd 100644 --- a/components/input/src/input/input.js +++ b/components/input/src/input/input.js @@ -1,4 +1,5 @@ import { theme, colors, spacers, sharedPropTypes } from '@dhis2/ui-constants' +import { IconCross16 } from '@dhis2/ui-icons' import { StatusIcon } from '@dhis2-ui/status-icon' import cx from 'classnames' import PropTypes from 'prop-types' @@ -8,8 +9,9 @@ import { inputTypes } from './inputTypes.js' const styles = css` .input { - display: flex; + display: inline-flex; align-items: center; + position: relative; gap: ${spacers.dp8}; } @@ -127,6 +129,15 @@ export class Input extends Component { } } + handleClear = () => { + if (this.props.onChange) { + this.props.onChange({ + value: '', + name: this.props.name, + }) + } + } + createHandlerPayload(e) { return { value: e.target.value, @@ -155,10 +166,22 @@ export class Input extends Component { step, autoComplete, dataTest = 'dhis2-uicore-input', + clearable, + prefixIcon, + width, } = this.props return ( -
+
+ {prefixIcon && {prefixIcon}} + {clearable && value?.length ? ( + + ) : null} {styles}
) @@ -209,6 +278,8 @@ Input.propTypes = { /** The [native `autocomplete` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-autocomplete) */ autoComplete: PropTypes.string, className: PropTypes.string, + /** Makes the input field clearable */ + clearable: PropTypes.bool, dataTest: PropTypes.string, /** Makes the input smaller */ dense: PropTypes.bool, @@ -228,6 +299,8 @@ Input.propTypes = { name: PropTypes.string, /** Placeholder text for the input */ placeholder: PropTypes.string, + /** Add prefix icon */ + prefixIcon: PropTypes.element, /** Makes the input read-only */ readOnly: PropTypes.bool, /** Sets a role attribute on the input */ @@ -243,6 +316,8 @@ Input.propTypes = { value: PropTypes.string, /** Applies 'warning' appearance for validation feedback. Mutually exclusive with `valid` and `error` props */ warning: sharedPropTypes.statusPropType, + /** Defines the width of the input. Can be any valid CSS measurement */ + width: PropTypes.string, /** Called with signature `({ name: string, value: string }, event)` */ onBlur: PropTypes.func, /** Called with signature `({ name: string, value: string }, event)` */ diff --git a/components/input/types/index.d.ts b/components/input/types/index.d.ts index e9bca202d9..ed135286b9 100644 --- a/components/input/types/index.d.ts +++ b/components/input/types/index.d.ts @@ -41,6 +41,10 @@ export interface InputProps { */ autoComplete?: string className?: string + /** + * Makes the input clearable + */ + clearable?: boolean dataTest?: string /** * Makes the input smaller @@ -78,6 +82,10 @@ export interface InputProps { * Placeholder text for the input */ placeholder?: string + /** + * Add prefix icon + */ + prefixIcon?: Element /** * Makes the input read-only */ @@ -135,6 +143,10 @@ export interface InputFieldProps { */ autoComplete?: string className?: string + /** + * Makes the input field clearable + */ + clearable?: boolean dataTest?: string /** * Makes the input smaller @@ -184,6 +196,10 @@ export interface InputFieldProps { * Placeholder text for the input */ placeholder?: string + /** + * Add prefix icon to input + */ + prefixIcon?: Element /** * Makes the input read-only */