diff --git a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap index 02c7cae7815..3f2a5a14210 100644 --- a/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap +++ b/src/components/inline_edit/__snapshots__/inline_edit_form.test.tsx.snap @@ -27,6 +27,7 @@ exports[`EuiInlineEditForm Edit Mode editModeProps.cancelButtonProps 1`] = ` class="euiFormControlLayout__childrenWrapper" > +
+
+
+
+
+
+
{ }); }); }); + + describe('keyboard events', () => { + test('pressing the Enter key saves text and returns to readMode', () => { + const { getByTestSubject, getByText } = render( + + ); + + fireEvent.change(getByTestSubject('euiInlineEditModeInput'), { + target: { value: 'New message!' }, + }); + fireEvent.keyDown(getByTestSubject('euiInlineEditModeInput'), { + key: 'Enter', + }); + + expect(getByTestSubject('euiInlineReadModeButton')).toBeTruthy(); + expect(getByText('New message!')).toBeTruthy(); + }); + + test('pressing the Escape key cancels text changes and returns to readMode', () => { + const { getByTestSubject, getByText } = render( + + ); + + fireEvent.change(getByTestSubject('euiInlineEditModeInput'), { + target: { value: 'New message!' }, + }); + fireEvent.keyDown(getByTestSubject('euiInlineEditModeInput'), { + key: 'Escape', + }); + + expect(getByTestSubject('euiInlineReadModeButton')).toBeTruthy(); + expect(getByText('Hello World!')).toBeTruthy(); + }); + + it('calls passed `inputModeProps.onKeyDown` callbacks', () => { + const onKeyDown = jest.fn(); + + const { getByTestSubject, getByText } = render( + + ); + + fireEvent.change(getByTestSubject('euiInlineEditModeInput'), { + target: { value: 'New message!' }, + }); + fireEvent.keyDown(getByTestSubject('euiInlineEditModeInput'), { + key: 'Enter', + }); + + // Both EUI and consumer `onKeyDown` events should have run + expect(onKeyDown).toHaveBeenCalled(); + expect(getByTestSubject('euiInlineReadModeButton')).toBeTruthy(); + expect(getByText('New message!')).toBeTruthy(); + }); + }); }); }); diff --git a/src/components/inline_edit/inline_edit_form.tsx b/src/components/inline_edit/inline_edit_form.tsx index 4bc3a88d007..7ac900295c6 100644 --- a/src/components/inline_edit/inline_edit_form.tsx +++ b/src/components/inline_edit/inline_edit_form.tsx @@ -12,6 +12,7 @@ import React, { useState, HTMLAttributes, MouseEvent, + KeyboardEvent, } from 'react'; import classNames from 'classnames'; @@ -29,8 +30,8 @@ import { EuiButtonIconPropsForButton } from '../button/button_icon'; import { EuiButtonEmptyPropsForButton } from '../button/button_empty/button_empty'; import { EuiFlexGroup, EuiFlexItem } from '../flex'; import { EuiSkeletonRectangle } from '../skeleton'; -import { useEuiTheme } from '../../services'; -import { useEuiI18n } from '../i18n'; +import { useEuiTheme, keys } from '../../services'; +import { EuiI18n, useEuiI18n } from '../i18n'; import { useGeneratedHtmlId } from '../../services/accessibility'; // Props shared between the internal form component as well as consumer-facing components @@ -139,6 +140,8 @@ export const EuiInlineEditForm: FunctionComponent = ({ 'Cancel edit' ); + const editModeDescribedById = useGeneratedHtmlId({ prefix: 'inlineEdit' }); + const [isEditing, setIsEditing] = useState(false || startWithEditOpen); const inlineEditInputId = useGeneratedHtmlId({ prefix: '__inlineEditInput' }); @@ -163,6 +166,17 @@ export const EuiInlineEditForm: FunctionComponent = ({ setIsEditing(false); }; + const editModeInputOnKeyDown = (event: KeyboardEvent) => { + switch (event.key) { + case keys.ENTER: + saveInlineEditValue(); + break; + case keys.ESCAPE: + cancelInlineEdit(); + break; + } + }; + const editModeForm = ( @@ -185,8 +199,22 @@ export const EuiInlineEditForm: FunctionComponent = ({ isLoading={isLoading} data-test-subj="euiInlineEditModeInput" {...editModeProps?.inputProps} + aria-describedby={classNames( + editModeDescribedById, + editModeProps?.inputProps?.['aria-describedby'] + )} + onKeyDown={(e: KeyboardEvent) => { + editModeInputOnKeyDown(e); + editModeProps?.inputProps?.onKeyDown?.(e); + }} /> +