From 02e14a45e669906d3da798e2cc593522bfb38d6d Mon Sep 17 00:00:00 2001 From: Shahzad Date: Fri, 5 Jan 2024 21:33:12 +0100 Subject: [PATCH] [EuiTextArea] Add `isClearable` and `icon` props (#7449) Co-authored-by: Cee Chen --- changelogs/upcoming/7449.md | 1 + src-docs/src/views/form_controls/text_area.js | 2 +- .../form/text_area/text_area.spec.tsx | 48 +++++++++++++++++++ src/components/form/text_area/text_area.tsx | 46 ++++++++++++++++-- 4 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 changelogs/upcoming/7449.md create mode 100644 src/components/form/text_area/text_area.spec.tsx diff --git a/changelogs/upcoming/7449.md b/changelogs/upcoming/7449.md new file mode 100644 index 00000000000..02dc06f6c01 --- /dev/null +++ b/changelogs/upcoming/7449.md @@ -0,0 +1 @@ +- Updated `EuiTextArea` to accept `isClearable` and `icon` as props diff --git a/src-docs/src/views/form_controls/text_area.js b/src-docs/src/views/form_controls/text_area.js index d78dfa530f8..ecce86b2cde 100644 --- a/src-docs/src/views/form_controls/text_area.js +++ b/src-docs/src/views/form_controls/text_area.js @@ -12,7 +12,7 @@ export default () => { return ( /* DisplayToggles wrapper for Docs only */ - + +/// +/// + +import React, { useState } from 'react'; +import { EuiTextArea } from './text_area'; + +describe('EuiTextArea', () => { + describe('isClearable', () => { + it('works for uncontrolled components', () => { + cy.realMount(); + + cy.get('textarea').type('hello world'); + cy.get('textarea').should('have.value', 'hello world'); + + cy.get('[data-test-subj="clearTextAreaButton"]').click(); + cy.get('textarea').should('have.value', ''); + }); + + it('works for controlled components', () => { + const ControlledTextArea = ({}) => { + const [value, setValue] = useState(''); + return ( + setValue(e.target.value)} + isClearable + /> + ); + }; + cy.realMount(); + + cy.get('textarea').type('hello world'); + cy.get('textarea').should('have.value', 'hello world'); + + cy.get('[data-test-subj="clearTextAreaButton"]').click(); + cy.get('textarea').should('have.value', ''); + }); + }); +}); diff --git a/src/components/form/text_area/text_area.tsx b/src/components/form/text_area/text_area.tsx index 1447c3cd6c0..d3253dc1742 100644 --- a/src/components/form/text_area/text_area.tsx +++ b/src/components/form/text_area/text_area.tsx @@ -6,18 +6,32 @@ * Side Public License, v 1. */ -import React, { TextareaHTMLAttributes, Ref, FunctionComponent } from 'react'; -import { CommonProps } from '../../common'; +import React, { + TextareaHTMLAttributes, + Ref, + FunctionComponent, + useRef, + useMemo, +} from 'react'; import classNames from 'classnames'; +import { CommonProps } from '../../common'; +import { useCombinedRefs } from '../../../services'; + import { EuiFormControlLayout } from '../form_control_layout'; import { EuiValidatableControl } from '../validatable_control'; import { useFormContext } from '../eui_form_context'; +import { EuiFormControlLayoutIconsProps } from '../form_control_layout/form_control_layout_icons'; export type EuiTextAreaProps = TextareaHTMLAttributes & CommonProps & { + icon?: EuiFormControlLayoutIconsProps['icon']; isLoading?: boolean; isInvalid?: boolean; + /** + * Shows a button that allows users to quickly clear the textarea + */ + isClearable?: boolean; /** * Expand to fill 100% of the parent. * Defaults to `fullWidth` prop of ``. @@ -52,9 +66,11 @@ export const EuiTextArea: FunctionComponent = (props) => { compressed, fullWidth = defaultFullWidth, id, + icon, inputRef, isLoading, isInvalid, + isClearable, name, placeholder, resize = 'vertical', @@ -82,11 +98,35 @@ export const EuiTextArea: FunctionComponent = (props) => { definedRows = 6; } + const ref = useRef(null); + const refs = useCombinedRefs([ref, inputRef]); + + const clear = useMemo(() => { + if (isClearable) { + return { + onClick: () => { + if (ref.current) { + ref.current.value = ''; + const event = new Event('input', { + bubbles: true, + cancelable: false, + }); + ref.current.dispatchEvent(event); + ref.current.focus(); // set focus back to the textarea + } + }, + 'data-test-subj': 'clearTextAreaButton', + }; + } + }, [isClearable]); + return ( @@ -96,7 +136,7 @@ export const EuiTextArea: FunctionComponent = (props) => { rows={definedRows} name={name} id={id} - ref={inputRef} + ref={refs} placeholder={placeholder} > {children}