mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Ingest Node Pipelines] Implement EuiInlineEdit
into Inline Text Input Component (#162398)
Included in https://github.com/elastic/eui/issues/6778 ## Summary Hi team! EUI recently released the `EuiInlineEdit` component and the Ingest Node Pipelines page was identified as a good candidate for the new component. This PR is replaces the inner workings of the `InlineTextInput` component and replaces it with the new `EuiInlineEdit` component. I've included screens below of this change, but would love to hear your feedback and ensure this component installation meets all of the Ingest Node Pipeline needs. **Ingest Node Pipelines (Read Mode)**  **Ingest Node Pipelines (Edit Mode)**  --- Changes I'd like to call out: - There's no tooltip surrounding inline edit that displays the placeholder or text value. `EuiInlineEdit` includes a `title` for the read mode button, so the value can be seen on hover. (This feature will make it into the next Kibana upgrade and will not require any additional changes). - The `placeholder` styling is slightly different than the previous version Design Question: Should the inline edit to be constrained to the left side of the pipeline? I didn't want to change this aspect without prior input. ### Checklist Delete any items that are not applicable to this PR. - ~[ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)~ - ~[ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials~ - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - ~[ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
ca9b4d0f35
commit
618c7fa32b
2 changed files with 10 additions and 112 deletions
|
@ -1,106 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import classNames from 'classnames';
|
||||
import React, { useState, useEffect, useCallback, memo } from 'react';
|
||||
import { EuiFieldText, EuiText, keys, EuiToolTip } from '@elastic/eui';
|
||||
|
||||
export interface Props {
|
||||
placeholder: string;
|
||||
ariaLabel: string;
|
||||
onChange: (value: string) => void;
|
||||
/**
|
||||
* Whether the containing element of the text input can be focused.
|
||||
*
|
||||
* If it cannot be focused, this component cannot switch to showing
|
||||
* the text input field.
|
||||
*
|
||||
* Defaults to false.
|
||||
*/
|
||||
disabled?: boolean;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
function _InlineTextInput({
|
||||
placeholder,
|
||||
text,
|
||||
ariaLabel,
|
||||
disabled = false,
|
||||
onChange,
|
||||
}: Props): React.ReactElement<any, any> | null {
|
||||
const [isShowingTextInput, setIsShowingTextInput] = useState<boolean>(false);
|
||||
const [textValue, setTextValue] = useState<string>(() => text ?? '');
|
||||
|
||||
const containerClasses = classNames('pipelineProcessorsEditor__item__textContainer', {
|
||||
'pipelineProcessorsEditor__item__textContainer--notEditing': !isShowingTextInput && !disabled,
|
||||
});
|
||||
|
||||
const submitChange = useCallback(() => {
|
||||
// Give any on blur handlers the chance to complete if the user is
|
||||
// tabbing over this component.
|
||||
setTimeout(() => {
|
||||
setIsShowingTextInput(false);
|
||||
onChange(textValue);
|
||||
});
|
||||
}, [setIsShowingTextInput, onChange, textValue]);
|
||||
|
||||
useEffect(() => {
|
||||
setTextValue(text ?? '');
|
||||
}, [text]);
|
||||
|
||||
useEffect(() => {
|
||||
const keyboardListener = (event: KeyboardEvent) => {
|
||||
if (event.key === keys.ESCAPE || event.code === 'Escape') {
|
||||
setIsShowingTextInput(false);
|
||||
}
|
||||
if (event.key === keys.ENTER || event.code === 'Enter') {
|
||||
submitChange();
|
||||
}
|
||||
};
|
||||
if (isShowingTextInput) {
|
||||
window.addEventListener('keyup', keyboardListener);
|
||||
}
|
||||
return () => {
|
||||
window.removeEventListener('keyup', keyboardListener);
|
||||
};
|
||||
}, [isShowingTextInput, submitChange, setIsShowingTextInput]);
|
||||
|
||||
return isShowingTextInput && !disabled ? (
|
||||
<div className={`pipelineProcessorsEditor__item__textContainer ${containerClasses}`}>
|
||||
<EuiFieldText
|
||||
controlOnly
|
||||
onBlur={submitChange}
|
||||
fullWidth
|
||||
compressed
|
||||
value={textValue}
|
||||
aria-label={ariaLabel}
|
||||
className="pipelineProcessorsEditor__item__textInput"
|
||||
inputRef={(el) => el?.focus()}
|
||||
onChange={(event) => setTextValue(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={containerClasses}
|
||||
tabIndex={disabled ? -1 : 0}
|
||||
onFocus={() => setIsShowingTextInput(true)}
|
||||
>
|
||||
<EuiToolTip content={text ?? placeholder}>
|
||||
<EuiText size="s" color="subdued">
|
||||
<div
|
||||
className="pipelineProcessorsEditor__item__description"
|
||||
data-test-subj="inlineTextInputNonEditableText"
|
||||
>
|
||||
{text || <em>{placeholder}</em>}
|
||||
</div>
|
||||
</EuiText>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const InlineTextInput = memo(_InlineTextInput);
|
|
@ -11,6 +11,7 @@ import {
|
|||
EuiButtonIcon,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiInlineEditText,
|
||||
EuiLink,
|
||||
EuiLoadingSpinner,
|
||||
EuiPanel,
|
||||
|
@ -30,7 +31,6 @@ import { getProcessorDescriptor } from '../shared';
|
|||
|
||||
import './pipeline_processors_editor_item.scss';
|
||||
|
||||
import { InlineTextInput } from './inline_text_input';
|
||||
import { ContextMenu } from './context_menu';
|
||||
import { i18nTexts } from './i18n_texts';
|
||||
import { Handlers } from './types';
|
||||
|
@ -213,12 +213,16 @@ export const PipelineProcessorsEditorItem: FunctionComponent<Props> = memo(
|
|||
className={inlineTextInputContainerClasses}
|
||||
grow={false}
|
||||
>
|
||||
<InlineTextInput
|
||||
disabled={isEditorNotInIdleMode}
|
||||
onChange={onDescriptionChange}
|
||||
ariaLabel={i18nTexts.processorTypeLabel({ type: processor.type })}
|
||||
text={description}
|
||||
<EuiInlineEditText
|
||||
size="s"
|
||||
defaultValue={description || ''}
|
||||
readModeProps={{ 'data-test-subj': 'inlineTextInputNonEditableText' }}
|
||||
placeholder={defaultDescription ?? i18nTexts.descriptionPlaceholder}
|
||||
inputAriaLabel={i18nTexts.processorTypeLabel({ type: processor.type })}
|
||||
isReadOnly={isEditorNotInIdleMode}
|
||||
onSave={(newTextValue) => {
|
||||
onDescriptionChange(newTextValue);
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue